<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
      xmlns:thr="http://purl.org/syndication/thread/1.0"
      xml:lang="fr">
    <title type="text">DarkBlog</title>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/" />
    <updated>2026-04-23T16:30:52Z</updated>

    <author>
        <name>DarkChyper</name>
    </author>
    <link rel="self" type="application/atom+xml" href="https://darkblog.lhoir.me/atom_fr.xml" />

    <subtitle type="text">Le blog de Simon Lhoir</subtitle>
    <id>https://darkblog.lhoir.me/</id>

    <entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2026-04-23-errances-04.html</id>
    <title type="html">Errances #04
</title>
    <updated>2026-04-23T16:30:52Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Errances #04
&lt;/h1&gt;
        &lt;img alt=&quot;&quot; src=&quot;https://darkblog.lhoir.me//assets/errances/04/2026-04-17-cover.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;blockquote&gt; Qu&#039;elles soient virtuelles, sportives ou perdues dans d&#039;autres mondes, voici le récap de ce que j’ai parcouru, vu et lu cette semaine.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Photo de l&#039;article : Vue depuis le troisième plateau du terril de Pinchonvalles - Liévin/Avion - 2026-04-17
&lt;/p&gt;&lt;h2&gt; Tracés
&lt;/h2&gt;&lt;p&gt;Matériel : Fitbit charge 6
&lt;/p&gt;&lt;p&gt;Logiciel : Strava + Affinity
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; 2026-04-17
&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/errances/04/2026-04-17.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/errances/04/2026-04-17.png&quot; alt=&quot;Tracé du vendredi 17 avril 2026. 7,45km, 1h26min, 139m de dénivelé positif
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;7,45km
&lt;/li&gt;&lt;li&gt;1h26min
&lt;/li&gt;&lt;li&gt;139m de dénivelé positif
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Cette sortie a été incroyable, elle a été épuisante autant physiquement que mentalement, mais dans le bon sens. D&#039;habitude, je ne vais pas marcher le vendredi, c&#039;est le jour des courses ou de la cuisine. Là, je suis parti sur un coup de tête, je me suis préparé à la dernière minute. Je ne sais pas si c&#039;est grâce au temps qu&#039;il faisait, au fait que je refaisais un parcours connu, ou à la playlist qui était parfaite, mais j&#039;ai réussi à totalement laisser mon esprit... errer.
&lt;/p&gt;&lt;p&gt;Je n&#039;avais jamais vraiment réussi à ressentir cela ni à me laisser porter par le flot de mon esprit. Alors je ne peux pas dire que cela a été productif, je n&#039;ai en réalité rien produit.
&lt;/p&gt;&lt;p&gt;Mais j&#039;ai librement cogité pendant 90 minutes. De jouer la musique dans ma tête à réfléchir aux projets perso en cours, aux articles que j&#039;aimerais écrire... un travail de rangement des pensées, mais sans y penser. Exactement le sentiment contraire de quand on reste happé par les vidéos YouTube ou autres fils algorithmiques des réseaux asociaux.
&lt;/p&gt;&lt;p&gt;Je ne dirais pas un état de transe, bien qu&#039;il y ait des sections du parcours que je ne me rappelle pas avoir parcourues. Sans doute les endorphines dues au sport, je ne sais pas. En tout cas, je me sentais bien mieux après la séance que toutes les semaines précédentes. 
&lt;/p&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;p&gt;Je suis embêté avec cette section. J&#039;adore le fait de partager mes parcours. Au-delà de me motiver à faire de la marche, j&#039;alterne ces sorties entre parcours fixes pour quantifier mes progrès, et d&#039;autres sorties où je me laisse plus guider par l&#039;envie de découverte. Par contre, le processus actuel pour obtenir ces images et ces statistiques est vraiment chronophage, rébarbatif et me démotive à créer ces articles.
&lt;/p&gt;&lt;p&gt;Je dois récupérer tracés et données depuis Strava, et forcément sur mobile car il n&#039;y a pas les images sous fond transparent depuis un navigateur (è_é). M&#039;envoyer ces fichiers sur un ordinateur, puis dans le logiciel de retouche photo. Exporter ces images en les plaçant dans le bon dossier et rédiger la partie textuelle de ces données. Lourd...
&lt;/p&gt;&lt;p&gt;J&#039;ai commencé à développer un script pour automatiser tout cela. Mais rien que la partie Strava m&#039;a pris un temps fou, et pour le moment je n&#039;ai pas eu le temps de le terminer.
&lt;/p&gt;&lt;p&gt;Pourquoi vouloir automatiser cela ? Les statistiques, la trace... tout ça c&#039;est sympa surtout pour moi, pour pouvoir voir mes progrès hors outils fermés. Mais la partie la plus intéressante, et sur laquelle je veux mettre le plus d&#039;énergie, c&#039;est la retranscription de mon ressenti, de mes pensées pendant la sortie.
&lt;/p&gt;&lt;p&gt;Je ne suis pas content de ma montre de sport. Il n&#039;y a pas de baromètre et donc je n&#039;ai pas du tout les informations d&#039;altitude directement. Peut-être qu&#039;avec un outil adapté et la trace GPS brute je pourrais récupérer l&#039;information et calculer le dénivelé positif de la session. En tout cas c&#039;est ce qui fait que je n&#039;ai pas regardé si Fitbit me permettait de récupérer les informations des sessions de sport, et que je passe par Strava qui me mâche le travail au prix d&#039;un abonnement et d&#039;un enfermement de mes données.
&lt;/p&gt;&lt;p&gt;Je regarde pour utiliser autre chose qui serait un peu plus ouvert, ou d&#039;où il serait plus facile d&#039;extraire les données, au plus proche de la montre. Du côté de Garmin par exemple mais encore plus du côté de Polar qui est le seul acteur encore européen sur ce secteur.
&lt;/p&gt;&lt;p&gt;Si vous avez des retours de bidouilleurs-sportifs à me faire, je suis très preneur.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;En attendant, je ne vais pas mettre plus de tracé aujourd&#039;hui, et prendre du temps dès que possible pour finir le script d&#039;automatisation.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; URL
&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Vx7cVjxFcYY&amp;list=LL&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Interdire ou empêcher : la frontière floue de notre liberté
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Une vidéo courte de la chaîne &quot;Clever cloud&quot; que je trouve très intéressante. Certainement extraite d&#039;un échange bien plus long. On y aborde ici la différence entre l&#039;interdit et le fait d&#039;empêcher. Au début ses exemples sont plutôt simplistes. Mais le coup de la ceinture de sécurité est vraiment très intéressant. Cela amène le débat sur la gestion de la responsabilité et de l&#039;infantilisation, au sens juridique du terme, de l&#039;utilisateur. On passe alors d&#039;un régime de liberté avec des interdits à autre chose, un système sous supervision où l&#039;on déresponsabilise l&#039;utilisateur final.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://shows.acast.com/tronche-de-tech/episodes/69-solomon-hykes-le-createur-de-docker&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Podcast &quot;Tronche de Tech&quot; - Solomon Hykes - Le créateur de Docker
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Encore un épisode vraiment intéressant du podcast tech français &quot;Tronche de Tech&quot;. Au-delà du créateur de Docker, de la genèse de ce qui va révolutionner le cloud, la seconde partie de l&#039;interview porte sur la puissance des grands acteurs du secteur, et leur volonté de ralentir la croissance des petites start-up, quand elles lancent une bombe technologique comme Docker en open source, et de les figer très tôt dans des &quot;standards&quot;. Des &quot;standards&quot; qui se veulent &quot;plus ouverts et plus compatibles&quot;, chose contre laquelle on ne peut pas dire &quot;bah non je veux plus fermé et moins interopérable&quot;, mais qui ne fait que jouer sur les mots pour casser la concurrence. Solomon prend d&#039;ailleurs l&#039;exemple de Red Hat qui a subi la même chose 15 ans avant Docker et qui a pourtant fait partie de ce même jeu contre Docker.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://www.arte.tv/fr/videos/126484-047-A/tracks/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Tracks - Off Grid
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;J&#039;ai l&#039;impression d&#039;avoir déjà vu une vidéo similaire il y a un an. En tout cas j&#039;avais déjà regardé pour du matériel LoRa et compatible avec Meshtastic. Cet épisode de Tracks change un peu les choses. Il n&#039;y a pas d&#039;antenne relais près de chez moi pour ce réseau off grid. Alors mettre une antenne sur le toit du cabanon au fond du jardin me semblait peu utile. Mais depuis le début d&#039;année, je me balade régulièrement sur le terril à côté de chez moi, et là ça deviendrait bien plus intéressant d&#039;y poser une antenne autonome car beaucoup plus susceptible de créer un maillage avec les antennes un peu plus lointaines. Bref, encore une lubie dans ma liste de choses à explorer, mais avec un double intérêt...
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; IRL
&lt;/h2&gt;&lt;p&gt;Ni livre, ni revue cette semaine, et ce depuis pas mal de semaines en fait :(
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Dans ma tête
&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Cela faisait un bon moment que je n&#039;avais pas pris le temps d&#039;écrire un peu. Ce n&#039;était pas l&#039;envie qui me manquait mais bien le temps. C&#039;est un peu la folie au bureau, ce job est tellement intéressant et tellement multi-casquette qu&#039;il me prend beaucoup de temps. Ce qui me ravit, mais du coup j&#039;essaye de mieux utiliser les périodes plus creuses pour les loisirs, le perso.
&lt;/p&gt;&lt;p&gt;J&#039;avais pourtant pas mal d&#039;idées d&#039;articles dernièrement. Mais j&#039;ai surtout eu le syndrome de &quot;cette réunion aurait pu être un e-mail&quot;. Est-ce que ces idées d&#039;articles ne pourraient pas être simplement un pouet sur Mastodon ? Y a-t-il assez de matière à écrire ?
&lt;/p&gt;&lt;p&gt;Je me pose encore trop de questions. Écrire un petit article, rapide, juste pour mettre une idée sur le papier numérique, cela peut valoir le coup. Je me suis rendu compte de mon blocage et de son incohérence en lisant quelques articles du blog de Genma. Je suis parfois surpris qu&#039;un article ne fasse que deux petits paragraphes. Au début, je trouvais cela dommage de ne pas approfondir plus le sujet traité, cela sonnait comme un mémo, une introduction.
&lt;/p&gt;&lt;p&gt;En y réfléchissant un peu, et à force de lire ces articles courts mais réguliers, je me rends compte qu&#039;il a totalement raison. Sans parler de course à la publication, le nombre d&#039;idées rapides que je n&#039;ai jamais pris le temps d&#039;écrire, car je ne veux pas me contenter d&#039;un article court, est bien trop élevé. Et puis des articles courts prennent potentiellement moins de temps à écrire, relire, valider... donc cela peut se faire plus facilement entre deux bugs DMX :)
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blog.genma.fr/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le blog de Genma
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2026-04-23-errances-04.html" />
    
    <published>2026-04-23T16:30:52Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2026-02-13-errances-03.html</id>
    <title type="html">Errances #03
</title>
    <updated>2026-02-13T10:04:38Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Errances #03
&lt;/h1&gt;
        &lt;img alt=&quot;&quot; src=&quot;https://darkblog.lhoir.me//assets/errances/03/2026-02-09-cover.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;blockquote&gt; Qu’elles soient virtuelles, sportives ou perdues dans d’autres mondes, voici le récap de ce que j’ai parcouru, vu et lu ces deux dernières semaines.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Photo de l&#039;article : 2026-02-09 Véloroute du bassin minier
&lt;/p&gt;&lt;h2&gt; Tracés
&lt;/h2&gt;&lt;p&gt;Ces deux dernières semaines, des petites marches en villes et deux sorties longues :)
&lt;/p&gt;&lt;p&gt;Matériel : Fitbit charge 6
&lt;/p&gt;&lt;p&gt;Logiciel : Strava + Affinity
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; 2026-02-04 à 2026-02-06
&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/errances/03/2026-02-04.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/errances/03/2026-02-04.png&quot; alt=&quot;Une des 3 marches non sportive en ville
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;3 petites marches en centre ville cette semaine dans le cadre du boulot. Rien de foufou, c&#039;est du plat, je suis tout le temps arrété par les feux de signalisation. Ce n&#039;était pas une semaine sportive (j&#039;ai même repris méchamment du poids :( )
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; 2026-02-09
&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/errances/03/2026-02-09.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/errances/03/2026-02-09.png&quot; alt=&quot;Tracé du lundi 09 février 2026. 6,93km, 1h24min, 109m de dénivelé positif
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;6,93km
&lt;/li&gt;&lt;li&gt;1h24min
&lt;/li&gt;&lt;li&gt;109m de dénivelé positif
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Toute la matinée et tout le début de cette marche, je me disais &quot;non tu ne le fera pas, t&#039;es crevé, tu ne vas pas faire ce terril aujourd&#039;hui&quot;. Et pourtant :) C&#039;est toujours aussi difficile, je m&#039;arrête plein de fois pendant la montée, mais j&#039;ai crié ma joie une fois le sommet atteint. Et pardon à la dame que j&#039;ai croisé moins d&#039;une minute après ce cri, et qui m&#039;a regardé bizzarement :D
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; 2026-02-11
&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/errances/03/2026-02-11.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/errances/03/2026-02-11.png&quot; alt=&quot;Tracé du mercredi 11 février 2026. 7,24km, 1h18min, 87m de dénivelé positif
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;7,24km
&lt;/li&gt;&lt;li&gt;1h18min
&lt;/li&gt;&lt;li&gt;87m de dénivelé positif
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Les 300 premiers mètres ont été une torture : jambes lourdes, dessus de cuisses en feu, souffle court et le palpitant qui fait n&#039;importe quoi. J&#039;avais un peu imaginé le circuit que je voulais faire aujourd&#039;hui, mais avec ce début je pensais abandonner rapidement. Mais je n&#039;ai rien lâché et j&#039;en suis fier. Bon je risque d&#039;avoir des grosses crampes d&#039;ici 2 jours donc hydratation au max. Il faudrait que j&#039;aprenne à faire des étirements aussi, je pense que ca devient critique.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; URL
&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://medium.com/@PierreCol/retraites-et-si-on-arr%C3%AAtait-dopposer-les-g%C3%A9n%C3%A9rations-9bbdd999544e&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Retraites : et si on arrêtait d’opposer les générations ?
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Un article très intéressant de Pierre Col sur le sujet des retraites, abordé depuis son propre point de vue, puisqu’il y expose les calculs liés à sa retraite qui approche. Une vision qui se veut sans conflit de génération et qui revient sur des faits peu repris dans les médias traditionnels, comme le salaire de début de carrière à son époque comparé à celui d’aujourd’hui.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://piaille.fr/@nicolay_lilicre/116002765033577947&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Toot de @nicolay_lilicre@piaille.fr concernant Linux NIRD
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Un message de ce professeur de mathématiques, docteur et ancien ingénieur en sciences de l’alimentation, qui partage un moment touchant : des élèves réparent un ordinateur portable avec un peu de son aide et y installent une distribution Linux NIRD.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://nird.forge.apps.education.fr/linux/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Distributions linux NIRD pour les écoles primaires et secondaires
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Des distributions Linux conçues par et pour des professeurs des écoles, du primaire au secondaire.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=UZjPHnN482M&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;La trouvaille glaçante d&#039;un journaliste sur nos téléphones - Undescore_
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Vous trouvez que l’actualité est anxiogène en ce moment ? Vous n’avez encore rien vu. Quand toute notre vie numérique est tracée, enregistrée, vendue… tout devient possible pour les publicitaires… mais pas seulement.
&lt;/p&gt;&lt;p&gt;Si vous êtes sous android, allez dans : 
&lt;/p&gt;&lt;blockquote&gt; paramètres android / Google / Tous les services / Annonces 
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Et là vous pouvez supprimer votre ID publicitaire. Certaines version d&#039;android ne permettent que le renouvèlement de cet ID, pensez à le faire régulièrement. Ca n&#039;empêchera pas les app de tenter de vous traquer, mais ca leur met des batons dans les roues, c&#039;est toujours ça de pris.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://siddhantkhare.com/writing/ai-fatigue-is-real&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;AI fatigue is real and nobody talks about it - EN
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Si vous utilisez régulièrement des LLM pour générer du code, des projets ou tout autre travail professionnel, vous avez sans doute déjà ressenti une certaine fatigue s’installer en vous. Cet article met des mots sur ce mal dont peu de gens parlent et propose également des pistes pour mieux utiliser l’IA, afin de moins la subir.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://flus.fr/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Flus, le complément éditorial de votre veille 
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Un outil libre pour la gestion de sa veille quotidienne avec prise de notes. Je cherchais justement un moyen de compiler les liens d’articles que je lis sur différents supports.
&lt;/p&gt;&lt;p&gt;Flus est un outil entièrement web, utilisable sur smartphone sans application dédiée, et propose également une extension pour navigateur. Le service prend en charge les flux RSS/Atom, et son prix est libre lui aussi. Le code étant open source, il est tout à fait possible d’auto-héberger sa propre instance.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; IRL
&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://www.recyclivre.com/products/1192701-surveillance-les-libertes-au-defi-du-numerique-comprendre-et-agir&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;surveillance://: Les libertés au défi du numérique : comprendre et agir - Trsitant Nitot - C &amp; F Éditions 
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je triche un peu car je ne l’ai pas encore terminé. Mais la lecture de ce livre risque d’être lente, voire de se faire en plusieurs temps. Pile dans la lignée du lien vers la chaîne Underscore plus haut, on explique ici comment chacune de nos actions, de nos interactions dans le monde numérique est traquée, enregistrée et utilisée à des fins plus ou moins louables.
&lt;/p&gt;&lt;p&gt;Je n’en suis qu’à la partie explicative du sujet, qui est sans doute la plus anxiogène tant elle met des mots, des faits, sur ce que l’on savait déjà plus ou moins depuis longtemps. J’ai hâte d’arriver au moment des solutions possibles pour limiter cette traque.
&lt;/p&gt;&lt;p&gt;Une lecture difficile moralement mais que tout le monde devrait avoir lu avant d&#039;utiliser la moindre application ou réseau privateur &quot;gratuit&quot;.
&lt;/p&gt;&lt;p&gt;ISBN : 9782915825657
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Dans ma tête
&lt;/h2&gt;&lt;p&gt;Bon, je me rends à l’évidence : tenir un rythme hebdomadaire pour cette série d’articles, je n’en suis pas capable. Je n’ai ni les clefs ni le temps pour le faire. J’y arrivais sans trop de difficulté pour la vidéo, car je pouvais tout faire sur un même appareil, mon smartphone. Je rentabilisais mes trajets en TER pour avancer petit à petit dans le montage. Je ne me sens pas capable de sortir un laptop pour écrire dans ces conditions, et je n’en ai même pas envie.
&lt;/p&gt;&lt;p&gt;Je vais suivre les conseils de Ploum ; merci pour ton message d’encouragement, cela fait du bien d’avoir un petit retour de temps en temps, c’est motivant ; et me baser davantage sur mon flow d’écriture personnel que sur un système éditorial figé. Donc la prochaine publication pourrait être la semaine prochaine, dans deux semaines… ou encore moins souvent.
&lt;/p&gt;&lt;p&gt;En parlant de retours qui font du bien de temps en temps, je réfléchis à un système de commentaires / retours d’avis pour ce blog, dans un esprit Slow Web First.
&lt;/p&gt;&lt;p&gt;J’hésite entre deux versions.
&lt;/p&gt;&lt;p&gt;La première, la plus simple, serait d’avoir simplement un lien mailto en bas de chaque article avec en sujet « Re : titre de l’article ». C’est très simple à mettre en place, mais les retours ne seraient visibles que par moi, sauf si j’en fais une mise à jour de l’article.
&lt;/p&gt;&lt;p&gt;La seconde est plus complexe à mettre en place. Chaque article générerait sa propre adresse email, et la partie « sujet » du mail servirait à définir le nom d’affichage de la personne qui poste un commentaire.
&lt;/p&gt;&lt;p&gt;De mon côté, un script viendrait faire le tri entre les mails provenant de ce système et le reste, puis dispatcherait le contenu des réponses dans des fichiers liés à chaque article. Il me reste à imaginer une interface simple et accessible pour venir valider — ou non — les commentaires, puis implémenter la mécanique permettant de republier l’article avec les nouveaux messages.
&lt;/p&gt;&lt;p&gt;Ce second système risque d’être un peu chronophage à mettre en place, mais le challenge est motivant.
&lt;/p&gt;&lt;p&gt;Je ferai peut-être, dans un premier temps, la première version le temps de développer la seconde… on verra
&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2026-02-13-errances-03.html" />
    
    <published>2026-02-13T10:04:38Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2026-02-01-errances-02.html</id>
    <title type="html">Errances #02
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Errances #02
&lt;/h1&gt;
        &lt;img alt=&quot;2026-01-26 Terril de Pinchonvalles&quot; src=&quot;https://darkblog.lhoir.me//assets/errances/02/2026-01-26-errances.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;blockquote&gt; Qu&#039;elles soient virtuelles, sportives ou perdues dans d&#039;autres mondes, voici le récap de ce que j’ai parcouru, vu et lu cette semaine.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Photo de l&#039;article : 2026-01-26 Terril de Pinchonvalles
&lt;/p&gt;&lt;h2&gt; Tracés
&lt;/h2&gt;&lt;p&gt;Cette semaine une unique sortie enregistrée, mais quelle sortie !
&lt;/p&gt;&lt;p&gt;Matériel : Fitbit charge 6
&lt;/p&gt;&lt;p&gt;Logiciel : Strava + Affinity
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; 2026-01-26
&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/errances/02/2026-01-26.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/errances/02/2026-01-26.png&quot; alt=&quot;tracé de ma marche du 26 janvier 2026. 7,81 km, 1h 33min, 118m de dénivelé positif
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;7,81 km
&lt;/li&gt;&lt;li&gt;1h 33min
&lt;/li&gt;&lt;li&gt;118m de dénivelé positif
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Aller on refait la même que la semaine dernière mais juste en un peu plus rapide... ho mais on passe par où si on tourne à droite à cette intersection... oups :)
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; URL
&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wiuQCFkxDZE&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Pourquoi votre smartphone ne dure pas 10 ans ? - Nowtech
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;J’aime beaucoup les vidéos “tech for good” de la chaîne NowTech. Ce que j’apprécie, c’est le ton : ni techno-béat, ni anti-tech par principe, plutôt un juste milieu qui prend en compte les attentes des vrais utilisateurs, tout en gardant une conscience de l’impact et de la durabilité. Ça reste du YouTube : le contenu est assez léger, on se pose plus de questions qu’on n’en résout, mais c’est justement ce qui le rend agréable et stimulant. Et ce n’est pas la première fois que j’entends cette idée d’un matériel informatique conçu avec des matériaux qui vieillissent bien, qu’on a envie de garder longtemps parce qu’on y tient, un peu comme une vieille montre, un bijou, ou même un vêtement.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.surchauffe.info/2026/01/necromancie-numerique-apple-vient-de.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Nécromancie numérique chez Apple
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Apple qui met à jour d&#039;anciennes version de iOS est suffisamment rare pour être souligné. L&#039;article ne cite pas de source donc je me permets d&#039;en ajouter une ci dessous. L&#039;article est cependant intéressant car il parle des potentiels usage dérivé de ces appareil &quot;obsolètes&quot; détournés pour faire simple réveils, générateur de bruits blanc ou encore babyphone.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.igen.fr/ios/2026/01/apple-renouvelle-les-certificats-indispensables-au-bon-fonctionnement-des-anciens-iphone-et-ipad-154497&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;une source pour l&#039;article précédent
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.radiofrance.fr/franceculture/podcasts/un-monde-connecte/l-ice-ou-l-arsenal-technologique-en-action-6817567&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;L&#039;ICE ou l&#039;arsenal technologique en action - Franceculture
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Vous n&#039;avez rien à cacher, donner toutes ses informations à des entités privées ou publiques ne vous pose pas de problème ? C&#039;est sans doute vrai jusqu&#039;à ce que le pays dans lequel vous vivez bascule d&#039;une démocratie à un état totalitaire. Quand toutes les technologies que l&#039;on adore se retournent contre nous ...
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://berealbook.incode.studio/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;bereal Book - Solène DRN
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je ne suis clairement pas la cible car je n&#039;utilise pas le réseau social BeReal, mais le projet est très intéressant et est développé par une développeuse en herbe qui partage ses créations sur Youtube. Vous uploadez votre archive de données BeReal et le site vous donne un PDF imprimable avec vos données. Tout se fait sur votre navigateur, rien n&#039;est uploadé sur son serveur (d&#039;après une de ses réponses sur youtube). Le code n&#039;est pas ouvert, c&#039;est un peu dommage.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=phiaRh-OcTc&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;La vidéo du projet BeReal de Solène DRN
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; IRL
&lt;/h2&gt;&lt;p&gt;Pas de livre terminé cette semaine, mais un en cours de lecture, cela arrivera prochainement.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Dans ma tête
&lt;/h2&gt;&lt;p&gt;Une semaine très chargée mentalement : un gros projet se termine au bureau. C’est à la fois épuisant et palpitant.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;La vidéo de NowTech m’a rappelé une réflexion que j’ai eue sur ce que j’aimerais avoir comme “smartphone” ou, plus exactement, comme panoplie geek. Sortir du “tout-en-un” est une approche qui me semble très intéressante. Et contrairement à des marques comme Boox ou consorts, c’est la partie multimédia que j’aimerais extraire du smartphone, pas la lecture d’articles…
&lt;/p&gt;&lt;p&gt;Un smartphone avec des matériaux de meilleure qualité, voire qui vieillissent bien. Un écran e-ink couleur, un APN avant et arrière, mais juste le nécessaire pour s’envoyer les “photos jetables” du quotidien : une liste de courses, l&#039;étiquette d&#039;un produit, un ticket de caisse pour la compta, scanner un QR code, faire un selfie rapide... La présence d’une prise jack pour la musique et les podcasts, et donc une grande capacité de stockage pour tout avoir offline.
&lt;/p&gt;&lt;p&gt;Un offline à deux niveaux, peut-être : une version sans data, juste les appels et les SMS. De quoi rester joignable et communiquer simplement, sans fioriture. Et un second mode vraiment totalement offline, matériellement. Un appareil avec au moins 2 à 3 jours d’autonomie.
&lt;/p&gt;&lt;p&gt;Le second objet serait une montre très orientée santé et sport. Un écran e-ink non tactile, de vrais boutons, peu connectée ; à la limite juste les notifications d’appel et les messages de ceux pour qui je souhaite les recevoir. Rien qui n’ait moins de 10 jours d’autonomie.
&lt;/p&gt;&lt;p&gt;Le dernier objet serait un appareil pour le multimédia : prise et consultation de photos et de vidéos en haute qualité. Les jeux tourneraient également dessus. Un appareil sans carte SIM, mais dans un form factor de smartphone (peut-être un peu plus grand), qui tire sa connectivité du smartphone. Ici, ce ne serait pas l’autonomie ou la sobriété la clé, mais les performances.
&lt;/p&gt;&lt;p&gt;On pourrait également ajouter un bracelet juste pour la nuit, gestion du sommeil et des réveils. Pas d&#039;écran, un seul bouton, une gestion via smartphone ou par câble sur un ordinateur. Une très grande autonomie et une recharge qui se fait en journée quand on ne le porte pas.
&lt;/p&gt;&lt;p&gt;Je ne savais pas si cette réflexion valait un article de blog entier ; ce format me semble bien adapté.&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2026-02-01-errances-02.html" />
    
    <published>2026-02-01T16:02:33Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2026-01-25-errances-01.html</id>
    <title type="html">Errances #01
</title>
    <updated>2026-01-26T13:26:23Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Errances #01
&lt;/h1&gt;
        &lt;img alt=&quot;20 janvier 2026 - Terril de Pinchonvalles troisième plateau&quot; src=&quot;https://darkblog.lhoir.me//assets/errances/01/Errances_01_20260120.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;blockquote&gt; Qu&#039;elles soient virtuelles, sportives ou perdues dans d&#039;autres mondes, voici le récap de ce que j’ai parcouru, vu et lu cette semaine.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Photo de l&#039;article : 20 janvier 2026 - Terril de Pinchonvalles troisième plateau
&lt;/p&gt;&lt;h2&gt; Tracés
&lt;/h2&gt;&lt;p&gt;Cette semaine 2 vraies sorties et 2 petites marches (10 min) enregistrées.
&lt;/p&gt;&lt;p&gt;Matériel : Fitbit charge 6
&lt;/p&gt;&lt;p&gt;Logiciel : Strava + Affinity
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; 2026-01-20
&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/errances/01/errances_trace_2026-01-20.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/errances/01/errances_trace_2026-01-20.png&quot; alt=&quot;tracé de ma marche du 20 janvier 2026. 7,20 km, 1h22, 112m de dénivelé positif
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;7,20 km 
&lt;/li&gt;&lt;li&gt;1h22
&lt;/li&gt;&lt;li&gt;112m de dénivelé positif
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Depuis des mois, quand je passe devant cette entrée du terril de Pinchonvalles, je me dis &quot;allez, la prochaine fois, je me motive et je le fais. Ca fera du cardio, ca sera bon pour moi&quot;. Mais je me dégonfle à chaque fois. Cette sortie, je la voulais tranquille, rapide. Pour m&#039;y remettre après un mois de décembre... décembre quoi :) Et finalement, je me suis dit qu&#039;au pire, je ferai demi tour si c&#039;est trop difficile. J&#039;ai adoré.
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; 2026-01-23
&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/errances/01/errances_trace_2026-01-23.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/errances/01/errances_trace_2026-01-23.png&quot; alt=&quot;tracé de ma marche du 23 janvier 2026. 4,59 km, 54 minutes, 46m de dénivelé positif
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;4,59 km
&lt;/li&gt;&lt;li&gt;54 minutes
&lt;/li&gt;&lt;li&gt;46m de dénivelé positif
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Deux trois petites courses à faire dans le centre ville ? Ok j&#039;y vais à pied et j&#039;esaye de faire un max de montées. Check !
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; URL
&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://mastodon.social/@hikingdude/115925916357972569&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Toot de Franz Graf @hikingdude#mastodon.social
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Un simple toot sur Mastodon. Le simple rappel que de partager ses découvertes du web sur son propre site, puis sur les réseaux cela aide à construire le web comme il a été imaginé au début. Le message qui m&#039;a donné l&#039;impulsion pour démarrer cette série d&#039;articles.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.geeks-curiosity.net/quitter-evernote-alternatives-auto-hebergement-degooglisation/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;« DéGooglisé » depuis 8 ans : comment j’ai quitté Evernote et ce que j’ai appris en chemin (partie 1/2)
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Le retour d&#039;expérience sur la dégooglisation de prise de note de Julianoe. Article très intéressant, retraçant tout le cheminement pour se réapproprier ses données personnelles en ligne. Article en deux parties.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4xq6bVbS-Pw&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;&quot;La fabrique à idiots&quot; sur la chaîne YouTube de Micode
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Court documentaire/réflexion autour de l&#039;IA et notre désapropriation de la connaissance, de la réflexion par soi-même au profit des LLM et autres moteurs de recherche. Je trouve le contenu intéressant, car il explique le fonctionnement de l&#039;apprentissage, de ce qui se passe dans le cerveau, et de comment ne plus utiliser incorrectement les LLM.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.arte.tv/fr/videos/RC-026860/high-school-radical/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;HIGH SCHOOL RADICAL - Arte / Max Laulom
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Adolescent, à l’occasion d’un échange scolaire, Max a découvert une Amérique idéalisée : les casiers de lycée, les matchs de foot, les road trips avec ses amis. Mais depuis, l’élection de Donald Trump a provoqué une rupture entre ses valeurs et celles de ses proches restés sur place. Un reportage que j&#039;ai trouvé bouleversant, en 4 parties (80min).
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://frenchspin.fr/2025/12/peut-on-degafamiser-sa-vie-rdv-tech/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Peut-on déGAFAMiser sa vie – RDV Tech - Podcast hors série
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je triche un peu pour cet épisode de podcast, car en réalité, je l&#039;ai écouté entre Noël et nouvel an, pendant que je réfléchissais à un moyen de partager ce que je consommais. D&#039;habitude, ce podcast traite de l&#039;actualité tech. Cet épisode est un hors-série. D&#039;habitude, bien que conscient des soucis liés aux GAFAM, le ton est plutôt techno enthousiaste, il parle peu des alternatives. Par contre l&#039;ambiance est vraiment très saine, très apaisé, jamais clivante. Cassim Montilla, l&#039;invité et journaliste pour Frandroid, explique ici son parcours pour déGAFAMiser sa vie depuis un peu plus d&#039;un an.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; IRL
&lt;/h2&gt;&lt;h3&gt; ET SI JE N&#039;ETAIS PAS DIEU ?: Chroniques d&#039;un chat
&lt;/h3&gt;&lt;p&gt;De Stefania Gander aux éditions Gander Books. Publié le 4 octobre 2024.
&lt;/p&gt;&lt;p&gt;ISBN : 979-1281230255
&lt;/p&gt;&lt;p&gt;Premier livre de cette année 2026. Une jolie petite histoire, simple et touchante, racontée du point de vue du chat tout juste adopté par une famille habitant en appartement. Un livre qui passe aussi rapidement que la vie de nos petites boules de poils, et qui te laisse ce petit pincement au cœur quand tu refermes la dernière page.
&lt;/p&gt;&lt;p&gt;Un livre sans prétention, mais pas sans effet. Si vous aimez les chats (ou si vous avez déjà été “choisi” par un chat), il y a de grandes chances que vous vous reconnaissiez dans pas mal de scènes. Et si vous n’aimez pas les chats... bon. Disons que ce livre pourrait être une tentative de conversion tout à fait honorable.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Dans ma tête
&lt;/h2&gt;&lt;p&gt;En 2025, j&#039;ai repris le projet de produire une minute de vidéo par semaine. Une minute de ce qui se passe dans ma vie, sans filtre (sauf pour les visages des enfants). C&#039;était un projet vraiment intéressant à réaliser, et il me tenait à cœur d&#039;aller au bout des 52 minutes produites (et même un peu plus avec 2 épisodes doubles). Mais, à la fin, c&#039;était plutôt épuisant. Toujours avoir en tête de sortir son smartphone pour faire des vidéos, au cas où ça tomberait dans mon montage. Et surtout, une année avec beaucoup moins de photos, alors qu&#039;on ne met pas de vidéo dans un album papier, que l&#039;on peut continuer de feuilleter 40 ans plus tard ...
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2025-01-13-une-minute-par-semaine.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Une minute par semaine
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Ce qui m&#039;a aussi un peu choqué, c&#039;est l&#039;espace disque que prennent ces minutes produites (et je ne parle même pas des rushes.). Sur mon drive shadow, cela représente 14,6 Go, en comptant les doublons &quot;sans masquage de visage&quot; pour 54 minutes en 1080p... Ça fait cher pour de simples vidéos du quotidien. Elles sont également sur Instagram, et sur Peertube. 1,9Go sur ce dernier réseau, cela me semble plus raisonnable, je devrai choisir un meilleur codec pour l&#039;encodage de ces vidéos, mais le but était de tout faire depuis le smartphone. Reste que même 2Go, c&#039;est beaucoup.
&lt;/p&gt;&lt;p&gt;Pour 2026, je cherchais à faire autre chose. Déjà, écrire plus, plus souvent. Et puis partager plus également. J&#039;aime bien les Digest de Thierry Crouzet, ses liens partagés chaque dimanche. Une photo de ce qu&#039;il voit depuis sa terrasse, et les liens de ce qu&#039;il a lu sur le net. J&#039;aime également le format de &quot;/home/lord&quot;, sa mensuelle pour parler de ses visionnages, de sa vie. Il y a un autre blog dans mon fil RSS, mais le nom m&#039;échappe, et pareil un de ses formats d&#039;article donne des infos sur la fréquentation de ses serveurs, comme la bande passante consommée...
&lt;/p&gt;&lt;p&gt;Tout cela me donnait envie de m&#039;y mettre également, un format récurrent. J&#039;y pense depuis quelques semaines, mais impossible de trouver le format qui j&#039;aimerais écrire. Puis pendant une de mes marches, un mot m&#039;est venu : pérégrinations.
&lt;/p&gt;&lt;blockquote&gt; Pérégrinations - forme moderne au pluriel : déplacements incessants en de nombreux endroits.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Le terme est trop pompeux à mon goût, et suggère, à mon avis, le fait de se rendre à des endroits de façon calculée, réfléchis. Le contraire de ce que j&#039;aime faire. Quand je pars pour une marche, je change souvent d&#039;avis sur l&#039;itinéraire que je prends. Je fais souvent à peu près le même tour, mais avec des variations. C&#039;est la même chose avec les articles que je lis. Je choisis les flux ou les comptes des réseaux sociaux auxquels je m&#039;abonne. Mais leur contenu et leur fréquence n&#039;est pas &quot;prédictible&quot;. Et donc j&#039;erre de lien en lien sur le net. Voilà ce que je vais faire, partager mes errances.
&lt;/p&gt;&lt;p&gt;Pour le moment, je me contenterrai de ces articles. Puis je pense que je créerai une page spéciale qui regroupera tous les liens afin de les retrouver plus facilement.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://lord.re&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Site de /home/lord
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://tcrouzet.com/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Site de Thierry Crouzet
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2026-01-25-errances-01.html" />
    
    <published>2026-01-25T15:46:20Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2026-01-01-bilan-2025-roadmap-2026.html</id>
    <title type="html">Bilan 2025, roadmap 2026 ?
</title>
    <updated>2026-01-01T12:14:31Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Bilan 2025, roadmap 2026 ?
&lt;/h1&gt;
        &lt;p&gt;Ça y est, 2025 est derrière nous. Une année assez étonnante, qui ne s’est pas du tout déroulée comme prévu. Enfin... s’il y avait vraiment un « prévu » dans toute cette histoire.
&lt;/p&gt;&lt;p&gt;Niveau personnel, ca va. Tout le monde va à peu près bien, ou est sous traitement si ce n&#039;est pas la grande forme, mais disons que c&#039;est à peu près stable. Je n&#039;ai pas à me plaindre. J’ai même enfin passé le pas d’une petite intervention chirurgicale qui a réglé un souci que je traînais depuis... j’ai envie de dire toujours, vu que ça date de mes 16 ans. Seulement 23 ans plus tard, j’ai pu mettre tout ça plus ou moins derrière moi. Je ne rentrerai pas dans les détails, mais ça m’a fait sourire que le groupe Ultra Vomit sorte un titre plus ou moins dans le thème : Miction impossible. (Bon, ce n’est clairement pas leur meilleure chanson.)
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ufB5Dh4Z2d4&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Ultra Vomit - MICTION: IMPOSSIBLE (SONDE DE B!TE)
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Niveau pro, ça a été beaucoup plus les montagnes russes. Heureusement, ça se termine bien. Mais ça n’a pas été simple d’en arriver là.
&lt;/p&gt;&lt;p&gt;Je n’ai pas envie de mettre des mots trop forts par écrit ici. J’aurais trop l’impression de me plaindre, alors que je n’ai pas vraiment de quoi. Disons simplement que, suite au changement de climat entre collègues au bureau (encore), et face à des décisions qui allaient systématiquement à l’encontre de mes principes, de mes convictions professionnelles (encore), de mon fonctionnement interne, je me suis retrouvé avec une seule idée en tête : faire n&#039;importe quoi... plutôt que d&#039;être devant cet ordinateur. Tout devenait plus plaisant que le boulot que je devais faire. Et pourtant, j’adore être développeur : on parle vraiment d’un métier passion.
&lt;/p&gt;&lt;p&gt;Le ménage, la lessive, la cuisine, la vaisselle, le rangement, faire du tri, faire les courses, se promener sans but, dehors, loin et longtemps. Tout, sauf &quot;ça&quot;.
&lt;/p&gt;&lt;p&gt;Comme je l’évoquais lors du bilan d’un an en télétravail total, ce n’est pas forcément une bonne idée d’avoir son bureau sur le palier, juste à côté de la chambre. Tant que ça va, tout va bien. Mais quand tout part en vrille, ces soucis pro deviennent les premières et les dernières choses que l’on voit chaque jour. Et là, la coupure avec la vie perso ne se fait plus.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2024-09-11-teletravail-bilan-1an.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Bilan de 1 an de télétravail
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;On peut dire ce que l’on veut sur le fonctionnement du système en France (ou plus largement en Europe), n’empêche qu’il m’a permis de prendre du temps.
&lt;/p&gt;&lt;blockquote&gt; Six mois.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Du temps pour retomber en pression, calmer mes pensées et mes nuits.
&lt;/p&gt;&lt;p&gt;Puis du temps pour réfléchir, écouter, lire, visionner et parler.
&lt;/p&gt;&lt;p&gt;Le temps de prendre conscience que je devais être accompagné : pour mieux comprendre la situation, mieux me comprendre. Mieux comprendre aussi que les signes étaient là depuis longtemps, que rien n’est arrivé &quot;comme ça&quot;, pour rien.
&lt;/p&gt;&lt;p&gt;Comprendre pourquoi je suis un multi-passionné, capable d’aller à fond dans une (ou plusieurs) passions pour tout arrêter du jour au lendemain (ou au moins réduire la voilure), une fois un certain but atteint. Un arrêt parfois brusque, sans pour autant détester ce que j’avais fait ou appris, et sans abandonner l’idée d’y revenir plus tard.
&lt;/p&gt;&lt;p&gt;Et de recommencer avec de nouvelles passions, de nouveaux terrains d’apprentissage, de nouvelles connaissances à découvrir et à assimiler, tout en profitant de mon background pour aller plus vite et plus loin. Mais sans jamais vraiment devenir un véritable expert. Maîtriser un sujet à multiples facettes, oui ; se focaliser sur une spécialité pointue, non.
&lt;/p&gt;&lt;p&gt;Un fonctionnement très déroutant pour beaucoup, qui limite fortement le sentiment d’appartenance à un « groupe ». Un fonctionnement qui ne veut pas non plus dire que l’on n’a pas de passion sur le long terme, ce qui est encore plus déroutant.
&lt;/p&gt;&lt;p&gt;Il y a une conférence TED qui a mis des mots sur tout cela. Celle de Emilie Wapnick : Why some of us don’t have one true calling.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.ted.com/talks/emilie_wapnick_why_some_of_us_don_t_have_one_true_calling&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Why some of us don&#039;t have one true calling
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je n’ai pas forcément l’impression de rentrer à 100 % dans cette définition, mais c’est ce qui s’en rapproche le plus. Disons simplement que je ne vois pas pourquoi je devrais me fixer des limites dans ce que je peux faire ou apprendre. Le but n’est pas toujours d’accomplir un objectif précis. Mais tout finit forcément par servir, à un moment ou à un autre. Et mon implication dans de nouvelles &quot;passions&quot; n&#039;est pas forcément aussi poussé que ce qui est expliquée dans la vidéo. Et dans un sens, travailler dans l&#039;informatique à toujours été plutôt évident pour mon entourage, même quand j&#039;ai choisi une autre voie durant mes études. Une évidence ? pour le secteur, peut être, pour choisir un, unique, métier en particulier (réseau ? infra ? backend ? un langage particulier ?), non.
&lt;/p&gt;&lt;p&gt;Ce que j&#039;ai également compris, c&#039;est que j&#039;allais devoir aligner ce fonctionnement dans le monde professionnel.
&lt;/p&gt;&lt;blockquote&gt; Je parle du « système » comme d’une aide, mais je dois surtout cette remontée en selle rapide à mon épouse. C’est parce qu’elle a été un soutien indéfectible, une oreille attentive, et le moteur de cette reconstruction, que tout cela n&#039;a finalement pris &quot;que&quot; six mois. Du fond du coeur, Merci.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Je ne sais pas si le job que j’ai trouvé aujourd’hui sera le job « parfait ». Encore une fois, si tant est qu’il doive exister un job parfait... mais je pense sincèrement qu’il correspond beaucoup mieux à mon mode de fonctionnement.
&lt;/p&gt;&lt;p&gt;Il s’agit d’un projet qui mélange du code haut niveau (PHP, front-end) mais aussi du code plus bas niveau en Go, peut-être même un peu de C si besoin. Du fonctionnement bas niveau de Linux, de l’embarqué, du matériel, de gestion de protocole DMX, du réseau. Mais aussi un lien direct avec le monde physique : des lumières, des machines, quelque chose qui se rapproche un peu de ma bifurcation universitaire (et en partie professionnelle) vers l’audiovisuel. Comme quoi, tout est utile.
&lt;/p&gt;&lt;p&gt;Un job de dingue, qui demande de ne pas avoir peur de toucher à plein de sujets, parfois très complexes à assembler, et qui a pour ambition de fonctionner partout dans le monde. Le tout pour apporter du fun et de la joie aux gens.
&lt;/p&gt;&lt;p&gt;Un job &quot;idéal&quot; qui a aussi son lot de compromis. Un retour partiel sur site (bien que cela sois très très souple sur ce point), dépendre à nouveau du train pour les trajets, imposer des journées d’école plus longues à mon fils certins jours. Des compromis compensés par une ambiance bien plus agréable, tout en restant professionnellement et intellectuellement exigeante. Et la découverte de nouvelles personnes aux métiers très divers : des devs, du support, mais aussi des ingés son, des graphistes. Des personnes qui utilisent les bons outils pour réaliser le meilleur de ce qu&#039;ils peuvent faire, pour créer et distribuer le projet le plus abouti possible. Un melting-pot qui me plaît beaucoup.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Je ne pensais pas que ce billet prendrai cette tournure. Je pensais parler des projets que je n’avais pas pu faire cette année, du temps passé sur YouTube (88 épisodes de Legend, par exemple) ou à écouter des podcast ; au moins 50 épisode de &quot;tronche de tech&quot; mais tous les épisode du rendez-vous tech de Patrick Beja également ; du poids que je n&#039;ai pas perdu (et que j&#039;ai même repris :/ ). Du fait que je n’ai finalement lu qu’un seul livre : Une sacrée envie de foutre le bordel, entretiens entre Jean-Louis Missika et Xavier Niel. Un titre qui collait plutôt bien à cette année. Mais j’ai aussi lu pas mal de blogs. Souvent avec des idées pas toujours complètement alignées aux miennes, mais qui donnent à réfléchir, à s’améliorer.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.jailu.com/une-sacree-envie-de-foutre-le-bordel/9782290425480&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Une sacrée envie de foutre le bordel
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je pensais aussi parler des projets que je voulais réaliser, un peu comme une roadmap ; et pas vraiment comme de bonnes résolutions.
&lt;/p&gt;&lt;p&gt;Finalement, je crois que je vais prendre les choses comme elles viennent cette année. Essayer de consolider ma place dans ma nouvelle entreprise. Monter en compétences sur tous les sujets du projet professionnel. Essayer d’arriver à des versions satisfaisantes de mes projets persos ; Tempo et ce blog surtout.
&lt;/p&gt;&lt;p&gt;Lire ce que je peux, et surtout ce qui me fait envie. Écrire encore plus ici. Plus régulièrement encore.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Et, même si ce n’est pas le titre que j’ai le plus écouté cette année (non celui que j&#039;ai le plus écouté est &quot;The emptiness machine&quot; de Linkin Park), c’est sans doute celui qui lui correspond le mieux : War du groupe Sum 41. Encore une fois, sans aucune prétention.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=l9iQzu9M5hY&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;titre &quot;War&quot; du groupe &quot;Sum 41&quot;
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/Sum_41&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;article wikipedia du groupe Sum 41
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://music.youtube.com/watch?v=KBV_zpMm_0Q&amp;si=GRf4aqj-YLfIQhbb&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;&quot;The Emptiness Machine&quot; du groupe Linkin Park&lt;/a&gt;&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2026-01-01-bilan-2025-roadmap-2026.html" />
    
    <published>2026-01-01T12:14:31Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-12-25-test-casque-conduction-osseuse.html</id>
    <title type="html">Un casque à conduction osseuse : pourquoi, et pour qui ?
</title>
    <updated>2025-12-26T08:58:23Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Un casque à conduction osseuse : pourquoi, et pour qui ?
&lt;/h1&gt;
        &lt;img alt=&quot;&quot; src=&quot;https://darkblog.lhoir.me//assets/2025-12-25-conduction-osseuse/le-casque.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Pour Noël 2024, je me suis fait offrir un casque à conduction osseuse de la marque Shokz. Cela faisait des années que l’idée me trottait dans la tête. Je passe la majeure partie de mon temps avec un casque ou des écouteurs sur les oreilles : j’adore la musique et les podcasts tech. Mais, avec le temps, j’ai commencé à m’inquiéter un peu pour mes tympans et mon oreille interne.
&lt;/p&gt;&lt;p&gt;J’ai longtemps repoussé cet achat, par crainte d’une qualité sonore médiocre, surtout en écoutant régulièrement du « gros son » comme le métal et ses dérivés. La conduction osseuse me paraissait encore assez abstraite, presque expérimentale, et j’avais du mal à imaginer un rendu à la hauteur de mes habitudes d’écoute.
&lt;/p&gt;&lt;p&gt;C’est finalement en faisant le bilan d’une année complète en télétravail que j’ai ressenti le besoin de franchir le pas. L’avis d’une collègue, qui utilise exclusivement ce type de casque pour le sport, m&#039;a confirmé l&#039;envie de l&#039;avoir sous le sapin. Curiosité, confort et préservation de l’audition ont fini par l’emporter.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2024-09-11-teletravail-bilan-1an.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Bilan de 1 an de télétravail 
&lt;/a&gt;&lt;/p&gt;&lt;blockquote&gt; Cet article n&#039;est pas sponsorisé, il s&#039;agit d&#039;un produit que mes parents m&#039;ont offert à Noël. Ce n&#039;est qu&#039;un retour d&#039;expérience et pas un test en tant que tel. Les propos tenus ne sont le reflet que de ma propre expérience avec le produit.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;À l’origine, cette idée de retour après un an d’utilisation devait donner lieu à un article écrit au fil du temps : une année pour tester l’appareil et me documenter sur ses technologies. Dans les faits, cela ne s’est pas vraiment passé comme prévu. J’ai bien pris quelques notes de manière régulière, ainsi que des photos en situation pour illustrer mes propos, mais cette capsule est finalement restée une page blanche presque jusqu’au moment de sa publication.
&lt;/p&gt;&lt;p&gt;Mon objectif reste le même : proposer un avis personnel, celui d’un utilisateur exigeant. Si j’ai longtemps repoussé l’achat de ce casque (que je n&#039;ai pas acheté donc :) ), c’est avant tout parce que la technologie me semblait très éloignée de ce que je connaissais. Aujourd’hui, il existe des casques à conduction osseuse très abordables (aux alentours de 30 euros), mais quitte à franchir le pas, je voulais tester ce qui se faisait de mieux, niveau qualité sonore, dans le genre.
&lt;/p&gt;&lt;p&gt;Autant on sait tous ce que cela fait de porter un casque ou des écouteurs, autant la conduction osseuse reste, à mon sens, beaucoup moins répandue. Une recherche rapide sur Google renvoie essentiellement des articles de marque qui, forcément, vantent les qualités de leurs produits. J’avais donc envie d’apporter un point de vue différent sur le sujet et de répondre aux questions que je me posais avant de me lancer : gêne à long terme, maux de tête, fatigue liée aux vibrations lors de longues sessions d’écoute...
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Conduction osseuse ?
&lt;/h2&gt;&lt;p&gt;Wikipédia présente l’ostéophonie (ou conduction osseuse) comme le phénomène de propagation du son jusqu’à l’oreille interne par les os du crâne. C’est notamment ce mécanisme qui nous fait percevoir notre propre voix comme plus grave lorsque nous parlons, comparé à l’écoute de son enregistrement.
&lt;/p&gt;&lt;p&gt;À l’origine, la conduction osseuse n’avait rien de grand public. Elle a longtemps été utilisée dans le domaine médical, notamment dans certains appareils auditifs, pour contourner des problèmes liés à l’oreille externe ou moyenne. Ces usages ont surtout permis de démontrer qu’il était possible d’entendre sans passer par le chemin “classique” du conduit auditif, une idée qui a progressivement fait son chemin hors du cadre strictement thérapeutique.	
&lt;/p&gt;&lt;p&gt;Cette particularité est aujourd’hui exploitée par certains casques audio qui transmettent le son par vibrations osseuses, en laissant le conduit auditif totalement libre. L’utilisateur peut ainsi écouter de la musique ou des podcasts tout en restant attentif aux sons de son environnement, une approche particulièrement appréciée pour les usages sportifs ou en mobilité.
&lt;/p&gt;&lt;p&gt;Attention cependant, cette technologie n’a rien de miraculeuse. Les basses sont très peu, voire pas du tout, perceptibles par ce procédé, et les aigus sont tronqués, ce qui limite forcément la qualité d’écoute musicale. Pour les personnes de ma génération (voire plus anciennes) cela peut donner l’impression d’écouter de la musique à travers un téléphone fixe à l&#039;ancienne, avec la bonne vielle balise RC qui faisait sauter l&#039;ADSL. Les améliorations audibles se situent principalement dans les aigus, qui ne sont plus brutalement coupés à 3,4 kHz. Shokz annonce une réponse pouvant monter jusqu’à 15 kHz ; à l’oreille, je dirais plutôt qu’on se situe autour des 10 kHz. On évite également les effets de craquements et de saturation caractéristiques des anciennes lignes téléphoniques, ce qui rend l’écoute nettement plus agréable malgré les limites inhérentes à la technologie.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/Ost%C3%A9ophonie&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;L&#039;Ostéophonie sur wikipedia
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.soundcore.com/fr/blogs/headphones/are-bone-conduction-headphones-safe&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Article de soundcore sur la conduction osseuse et ses &quot;risques&quot;
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Présentation du openrun pro 2
&lt;/h2&gt;&lt;p&gt;L&#039;openrun pro 2 est-il un casque à conduction osseuse ? Oui, mais pas uniquement.
&lt;/p&gt;&lt;p&gt;On retrouve bien la technologie de conduction osseuse, commune à la majorité des produits de la marque Shokz, mais elle est ici complétée par de petits haut-parleurs directionnels chargés d’envoyer une partie du son vers le conduit auditif, mais sans l&#039;obstrué.
&lt;/p&gt;&lt;p&gt;La marque présente ainsi l’OpenRun Pro 2 :
&lt;/p&gt;&lt;blockquote&gt;Découvrez l&#039;OpenRun Pro 2, le tout nouveau casque à conduction osseuse Shokz qui se démarque d’une qualité sonore redéfinie pour l’écoute à oreilles libres avec notre nouvelle technologie Shokz DualPitch™. Cette technologie repose sur un duo parfait entre un haut-parleur à conduction osseuse et un haut-parleur à conduction aérienne.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Ces haut-parleurs « hybrides » sont justement mis en avant comme la réponse aux principales limites de la conduction osseuse, et notamment au manque de basses.
&lt;/p&gt;&lt;p&gt;Concrètement, cette approche hybride vise à répartir intelligemment le spectre sonore. La conduction osseuse continue d’assurer la transmission des médiums et une partie des aigus, tandis que la conduction aérienne vient renforcer les fréquences basses et donner plus de corps à l’ensemble. Sur le papier, l’idée est séduisante.
&lt;/p&gt;&lt;p&gt;Sur le plan physique, l’OpenRun Pro 2 reprend le design caractéristique de la gamme Shokz. Le casque se pose sur les pommettes, avec un arceau rigide mais flexible qui contourne l’arrière de la tête. L’ensemble est léger, bien équilibré, qui est sesnsé se faire oublier. Aucun contact avec le conduit auditif, aucune pression sur les oreilles : le confort est clairement l’un des points forts du produit, surtout lors d’une utilisation prolongée.
&lt;/p&gt;&lt;p&gt;Côté usages, ce positionnement hybride le destine naturellement à une écoute en mouvement, pour l&#039;activité sportive extérieur selon la marque.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.shokz.com/products/openrun-pro2&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;La page de l&#039;openrun 2 pro sur le site de Shokz
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Mon expérience
&lt;/h2&gt;&lt;p&gt;L’unboxing de l’appareil est rapide. Dans la boîte, on trouve le boîtier de transport, qui contient lui-même le casque, ainsi qu’un câble USB-A / USB-C. C’est tout. Simple, mais efficace. Et oui, la recharge se fait désormais en USB-C directement sur l’appareil, ce qui change du connecteur propriétaire des anciennes générations. Le point positif de ce choix s’arrête cependant là, puisqu’il n’est pas possible de recharger le casque pendant l’écoute. Je ne sais pas s’il s’agit d’un choix délibéré ou d’une contrainte technique, mais je peux comprendre l’idée d’éviter de porter des batteries en charge aussi près de la tête...
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-12-25-conduction-osseuse/unboxing.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-12-25-conduction-osseuse/unboxing.jpg&quot; alt=&quot;Le coffret de transport contenant l&#039;OpenRun pro 2 et le cordon d&#039;alimentation usb-a/usb-c
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Le casque en lui-même est vraiment très léger et donne une bonne impression de solidité. Je n’ai eu aucune difficulté à le positionner correctement « sur les oreilles » lors de la première utilisation. Il est très agréable à porter et, une fois en place, il ne bouge absolument pas, sans pour autant exercer de pression au niveau des pommettes. J’ai en revanche mis un peu plus de temps à apprivoiser les différents boutons, mais simplement le temps d’en assimiler le fonctionnement.
&lt;/p&gt;&lt;p&gt;En parlant des boutons… désolé pour les bip-phobes qui me lisent. Chaque action, appui court ou long, allumage, appairage, réglage du volume, déclenche un signal sonore, voire une petite annonce vocale. Malheureusement, il n’est pas possible de les désactiver complètement. On peut toutefois en régler le volume sur trois niveaux distincts. Ce paramétrage se fait uniquement via l’application Shokz, dans un menu assez bien caché : Réglages &gt; Paramètres des invites. Un intitulé peu explicite, qui regroupe à la fois le choix de la langue (anglais ou chinois/coréen/japonais) et le volume de ces fameuses notifications.
&lt;/p&gt;&lt;p&gt;Sinon c&#039;est vraiment surprenant d&#039;entendre aussi clairement voix et musique. Je pense que les hauts parleurs (qui ne semblent pas desactivables) jouent un rôle majeur dans cette qualité sonore.
&lt;/p&gt;&lt;p&gt;Cela fait donc un an que j&#039;utilise ce casque, voici mon avis quant à son utilisation dans certains cas concrets.
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Le sport en extérieur
&lt;/h3&gt;&lt;p&gt;Réponse courte : oui... mais.
&lt;/p&gt;&lt;p&gt;Réponse longue : le casque fait exactement ce que l’on attend de lui. Il permet de pratiquer une activité sportive en extérieur (de la marche, pour ma part) tout en restant attentif à ce qui se passe autour de soi. En pleine nature, c’est tout simplement parfait : un son très correct, sans masquer le chant des oiseaux ni le bruissement des feuilles dans le vent. À tel point que, sauf lorsque je cherche à me motiver en calant mon rythme sur la musique, je me surprends régulièrement à baisser le volume pour améliorer l’équilibre entre musique et sons naturels.
&lt;/p&gt;&lt;p&gt;Évidemment, dès qu’un engin motorisé passe à proximité (camions en tête) le bruit ambiant prend le dessus sur la musique. C’est un compromis que je trouve parfaitement acceptable, puisque l’objectif premier reste de rester à l’écoute de son environnement.
&lt;/p&gt;&lt;p&gt;Si vous pratiquez votre sport exclusivement en milieu urbain, l’expérience est forcément moins agréable. En circulation « normale », ça passe. Dès qu’il y a des travaux, beaucoup de camions ou un trafic dense, beaucoup moins.
&lt;/p&gt;&lt;p&gt;J’ai testé ce casque dans différentes conditions climatiques et je n’ai rencontré aucun problème particulier à ce niveau. Je porte très régulièrement des lunettes de soleil, pratiquement par tous les temps ; une des “conséquences” de mon opération de la myopie au laser. Le port du casque avec des lunettes, mais aussi avec un bonnet ou une casquette, fonctionne parfaitement. J’aurais même tendance à dire que les basses sont légèrement renforcées lorsque le conduit auditif est partiellement obstrué, par un bandeau par exemple.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-12-25-conduction-osseuse/casque-lunettes-bandeau.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-12-25-conduction-osseuse/casque-lunettes-bandeau.jpg&quot; alt=&quot;Bandeau + lunettes + casque =&gt; validé
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-12-25-conduction-osseuse/casque-casquette-lunettes.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-12-25-conduction-osseuse/casque-casquette-lunettes.jpg&quot; alt=&quot;Casquette + lunettes + casques pour aller chercher le pain =&gt; validé
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Lors de mes recherches, je suis tombé sur une vidéo de Frandroid qui illustre très bien ces points. Je trouve sa conclusion un peu trop négative par rapport à mon expérience, même si le testeur n’utilisait pas la version 2 du casque. Si votre session comprend une courte portion en ville (15 minutes par exemple) avant de rejoindre des zones plus calmes, mon avis personnel est que le choix d’un casque à conduction osseuse reste pertinent. Je trouve même étonnant de renvoyer vers un casque à réduction active du bruit pour l&#039;utiliser dns la circulation, je trouve que c&#039;est une recommandation dangeureuse.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=KRnocxqNgMg&amp;list&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Pourquoi (ne pas) choisir la CONDUCTION OSSEUSE ? - Test des Shokz OpenRun Pro
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Dans les transports en commun
&lt;/h3&gt;&lt;p&gt;Réponse courte : non.
&lt;/p&gt;&lt;p&gt;Réponse longue : le casque n’est absolument pas conçu pour isoler des bruits extérieurs importants. Je ne recommande clairement pas son utilisation dans les transports en commun.
&lt;/p&gt;&lt;p&gt;Je ne renverrai pas forcément vers des casques à réduction active de bruit, qui impliquent souvent une pression sonore plus élevée, mais plutôt vers des casques circum-auraux offrant une bonne isolation passive. Pour ce type d’environnement, c’est bien plus adapté.
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Pour conduire ou faire du vélo
&lt;/h3&gt;&lt;p&gt;Réponse courte : non.
&lt;/p&gt;&lt;p&gt;Réponse longue : Non, tout simplement parce que c’est interdit par le Code de la route en France. Le port d’un dispositif émettant du son à l’oreille est prohibé, que ce soit en voiture, à moto ou à vélo.
&lt;/p&gt;&lt;p&gt;Quelques références pour étayer ce point :
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000041910422&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Article R412-6-1 - Code de la route
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.legifrance.gouv.fr/ceta/id/CETATEXT000034013213/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Rejet par le conseil d&#039;état, en 2017, de la demande du fabricant Shokz visant à exclure la conduction osseuse de cette interdiction
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.securite-routiere.gouv.fr/les-medias/les-faq/faq-radar/quels-sont-les-dispositifs-audios-autorises-pour-les-velos&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Article de la sécurité routière
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Au départ, j’avoue avoir été surpris que ce type de casque ne soit pas au moins toléré. Après tout, le conduit auditif reste libre et l’on perçoit clairement les sons de l’environnement. Mais après avoir expérimenté l’écoute au bureau ou à la maison, entouré de personnes qui me parlent, j’ai fini par comprendre cette position.
&lt;/p&gt;&lt;p&gt;On entend, c’est vrai... mais on n’est pas pleinement attentif. Les sons arrivent, mais l’attention est ailleurs. Écouter de la musique ou un podcast mobilise une partie de la concentration, ce qui rend plus difficile le suivi d’une discussion ou une vigilance réelle vis-à-vis de ce qui se passe autour de soi. On entend mieux les danges quand on est piéton, mais pas autrement. De ce point de vue, la technologie du casque ne change finalement pas grand-chose. 
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Pour faire le ménage, le bricolage
&lt;/h3&gt;&lt;p&gt;Réponse court : oui.
&lt;/p&gt;&lt;p&gt;Réponse longue : cet été, j’ai découvert le podcast audio Tronche de Tech (également disponible sur YouTube). J’ai ainsi enchaîné les cinquante premiers épisodes en bricolant dans mon cabanon ou en faisant le ménage à la maison, mais aussi pendant mes courses (hors trajet, donc).
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2025-07-28-le-cabanon.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le cabanon
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://podcastaddict.com/podcast/tronche-de-tech/4513537&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;&quot;Tronche de Tech&quot; sur podcast addict
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Pour toutes les tâches ménagères à la maison, c’est un usage où le casque excelle. La qualité sonore, clairement non hi-fi, est largement compensée par la légèreté de l’appareil, au point qu’on finit par l’oublier. Si vous restez statique dans une pièce équipée d’une chaîne hi-fi ou d’enceintes, celles-ci resteront évidemment plus agréables. En revanche, dès que l’on se déplace de pièce en pièce, le casque devient très pratique. Seule exception notable : passer l’aspirateur... là, ça ne fonctionne clairement pas. :)
&lt;/p&gt;&lt;p&gt;Pour le bricolage, dans le jardin en ce qui me concerne, c’est aussi très appréciable. Cela évite d’imposer ses podcasts ou sa musique à tout le voisinage, surtout quand le contenu ne les intéresse pas forcément. En revanche, je ne saurais trop recommander de ne pas négliger les EPI (équipements de protection individuelle) lors de l’utilisation de machines bruyantes ou dangereuses, et de couper le son lorsque la concentration doit être maximale.
&lt;/p&gt;&lt;p&gt;Enfin, pendant les courses, l’effet est assez surprenant. Le bruit des caddies, la musique d’ambiance et les annonces en fond deviennent suffisamment lointains pour rendre l’expérience un peu moins pénible. Oui, je n’aime pas faire les courses… ça se voit tant que ça ? :)
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Pour les visios et les appareils
&lt;/h3&gt;&lt;p&gt;Réponse courte : oui et non.
&lt;/p&gt;&lt;p&gt;Réponse longue : sous macOS (et très probablement sous Windows) je n’ai rencontré aucun problème de codec ou de compatibilité. Le son est très correct, aussi bien pour l’écoute de musique que pour les visioconférences, et le micro fait parfaitement le travail.
&lt;/p&gt;&lt;p&gt;En revanche, j’ai rencontré quelques difficultés sous Ubuntu. La configuration audio y était scindée selon le type d’appareil : soit je définissais le casque comme périphérique audio, avec alors un excellent rendu sonore mais sans micro fonctionnel ; soit je le déclarais comme micro-casque, auquel cas le micro était bien pris en compte, mais avec un son nettement plus métallique et dégradé. Un comportement assez surprenant, d’autant plus que la marque propose pourtant une gamme explicitement orientée vers les usages professionnels.
&lt;/p&gt;&lt;blockquote&gt;Si le format de cette section vous rappelle quelque chose, c&#039;est que vous avez lu l&#039;article de Flozz sur les VPN, sinon allez le lire.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://blog.flozz.fr/2025/12/14/cest-quoi-un-vpn-et-en-avez-vous-vraiment-besoin/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Article de Flozz sur les cest-quoi-un-vpn-et-en-avez-vous-vraiment-besoin 
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; L&#039;application Shokz
&lt;/h2&gt;&lt;p&gt;Ce n’est pas une nouveauté : chaque appareil moderne arrive désormais avec son application dédiée. C’est souvent agaçant, mais pour une fois, celle-ci n’est pas totalement inutile. Dans ce cas précis, elle permet notamment de lier son casque à un compte Shokz (ce qui reste heureusement optionnel), mais surtout de gérer les mises à jour du micrologiciel — un point qui s’est avéré très pratique à l’usage.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-12-25-conduction-osseuse/l-application.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-12-25-conduction-osseuse/l-application.jpg&quot; alt=&quot;Aperçu de l&#039;application
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;L’application permet également de configurer l’égaliseur ainsi que quelques options supplémentaires du casque. C’est aussi ici que l’on peut activer ou désactiver le Bluetooth multipoint. Et c’est probablement là que se situe mon principal reproche : devoir passer par une application pour gérer cette fonctionnalité alors que d’autres casques la proposent activée par défaut.
&lt;/p&gt;&lt;p&gt;D’ailleurs, en début d’année, le multipoint était tout simplement inutilisable. Avec deux sources connectées simultanément, l’une prenait systématiquement le pas sur l’autre, même sans action de ma part. Pour l’anecdote, en rentrant d’une marche, mon casque s’est reconnecté tout seul au PC du bureau, situé à l’étage, et a coupé la musique que j’écoutais sur mon téléphone. La portée Bluetooth est excellente… parfois un peu trop. Heureusement, plusieurs mises à jour ont corrigé ce comportement, et le problème ne s’est plus reproduit depuis.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Conclusion
&lt;/h2&gt;&lt;p&gt;J’ai utilisé ce casque de manière quasi quotidienne pendant les neuf premiers mois de l’année. Pour écouter des podcast ou de la musique en provenance des plateformes en lignes comme Youtube music ou Deezer, cela fonctionne très bien. Pour d&#039;autres supports plus qualitatifs je repasse sans hésiter sur un casque plus classique.
&lt;/p&gt;&lt;p&gt;Son usage a naturellement diminué à partir du moment où j’ai repris les transports en commun. En dehors de cela, je n’ai constaté ni gêne particulière ni fatigue notable liée à la conduction osseuse, en tout cas pas davantage qu’avec un casque plus classique.
&lt;/p&gt;&lt;p&gt;Je reste quand même curieux de tester un casque 100 % à conduction osseuse, histoire de voir ce que ça donne à l’usage et de comparer.
&lt;/p&gt;&lt;p&gt;Côté autonomie, rien à redire : la batterie tient largement la journée. C’est parfait pour mon usage à la maison, entre télétravail et activité sportive. Le seul vrai bémol reste l’absence d’extinction automatique tant que le Bluetooth est actif. Le casque reste alors en veille, même sans rien diffuser. Un détail, mais que la marque pourrait clairement améliorer avec une mise à jour.
&lt;/p&gt;&lt;p&gt;Bref, je suis clairement conquis par ce type de casque (hybride, donc). Et si vous hésitez à sauter le pas, je ne peux que vous encourager à essayer.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Pour aller plus loin, Shokz met à disposition les notices et certifications de ses appareils à l’adresse suivante :
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.shokz.com/pages/download&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;lien pour télécharger les notices et les certifications des appareils Shokz
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; TL;DR
&lt;/h2&gt;&lt;p&gt;Les points positifs :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Confort excellent, même sur de longues durées
&lt;/li&gt;&lt;li&gt;Idéal pour les activités en extérieur, surtout en milieu naturel.
&lt;/li&gt;&lt;li&gt;Léger, stable et compatible avec lunettes, bonnet ou casquette.
&lt;/li&gt;&lt;li&gt;Autonomie suffisante pour tenir une journée complète.
&lt;/li&gt;&lt;li&gt;Technologie hybride qui améliore nettement l’écoute par rapport aux modèles plus anciens.
&lt;/li&gt;&lt;li&gt;Très pratique pour le télétravail, le ménage ou le bricolage.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Les points négatifs :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Qualité sonore limitée pour une écoute musicale exigeante
&lt;/li&gt;&lt;li&gt;Peu adapté aux transports en commun et aux environnements très bruyants.
&lt;/li&gt;&lt;li&gt;Pas d’extinction automatique tant que le Bluetooth reste actif.
&lt;/li&gt;&lt;li&gt;Signaux sonores omniprésents et non desactivables
&lt;/li&gt;&lt;li&gt;Interdit pour la conduite et le vélo (réglementation française).
&lt;/li&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-12-25-test-casque-conduction-osseuse.html" />
    
    <published>2025-12-26T08:58:23Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-12-05-exceptions-go.html</id>
    <title type="html">Des exceptions en Go
</title>
    <updated>2025-12-05T16:19:36Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Des exceptions en Go
&lt;/h1&gt;
        &lt;img alt=&quot;&quot; src=&quot;https://darkblog.lhoir.me//assets/2025-12-05-exceptions-go/cover.webp&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Dans la philosophie du langage Golang, la gestion des erreurs doit se faire au plus proche de la source. Que ce soit dans son propre code ou via des dépendances, il est très courant, lors de l’appel d’une fonction, de récupérer un résultat et une erreur. Erreur qui vaut, dans la majorité des cas, nil.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-48&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-48&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;package main

import (
	&amp;quot;errors&amp;quot;
	&amp;quot;fmt&amp;quot;
	&amp;quot;strings&amp;quot;
)

func loadFile(name string) (string, error) {
	if strings.Contains(name, &amp;quot;missing&amp;quot;) {
		return &amp;quot;&amp;quot;, errors.New(&amp;quot;fichier introuvable&amp;quot;)
	}
	return &amp;quot;DATA:&amp;quot; + name, nil
}

func parseData(data string) (string, error) {
	if strings.Contains(data, &amp;quot;bad&amp;quot;) {
		return &amp;quot;&amp;quot;, errors.New(&amp;quot;données invalides&amp;quot;)
	}
	return strings.ToUpper(data), nil
}

func storeResult(name, data string) error {
	if strings.Contains(name, &amp;quot;readonly&amp;quot;) {
		return errors.New(&amp;quot;impossible d&amp;apos;écrire le résultat (readonly)&amp;quot;)
	}
	fmt.Println(&amp;quot;Résultat stocké pour&amp;quot;, name, &amp;quot;:&amp;quot;, data)
	return nil
}

func main() {
	files := []string{
		&amp;quot;file1&amp;quot;,             // OK
		&amp;quot;file_missing&amp;quot;,      // loadFile =&amp;gt; erreur
		&amp;quot;file_bad_format&amp;quot;,   // parseData =&amp;gt; erreur
		&amp;quot;file_readonly&amp;quot;,     // storeResult =&amp;gt; erreur
		&amp;quot;file2&amp;quot;,             // OK
	}

	for _, f := range files {
		fmt.Println(&amp;quot;== Traitement de&amp;quot;, f)

		data, err := loadFile(f)
		if err != nil {
			fmt.Println(&amp;quot;Erreur loadFile:&amp;quot;, err)
			continue 
		}

		parsed, err := parseData(data)
		if err != nil {
			fmt.Println(&amp;quot;Erreur parseData:&amp;quot;, err)
			continue
		}

		if err := storeResult(f, parsed); err != nil {
			fmt.Println(&amp;quot;Erreur storeResult:&amp;quot;, err)
			continue
		}

		fmt.Println(&amp;quot;Traitement terminé avec succès pour&amp;quot;, f)
	}

	fmt.Println(&amp;quot;\n=== Fin du programme ===&amp;quot;)
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cette gestion permet au programme Go de continuer son exécution et d’éviter les crashs violents.
&lt;/p&gt;&lt;p&gt;Mais parfois, on écrit du code dont l’objectif est justement de faire échouer l’exécution dès la première erreur sérieuse.
&lt;/p&gt;&lt;p&gt;Typiquement : un script d’installation, un outil système, un setup de machine… bref, des moments où si quelque chose ne va pas, on veut que ça s’arrête tout de suite.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-49&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-49&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;retour, err := MaFonction()
if err != nil {
	fmt.Println(&amp;quot;ERROR:&amp;quot;, err)
	os.Exit(-1)
}

retour2, err := MaFonction2()
if err != nil {
	fmt.Println(&amp;quot;ERROR:&amp;quot;, err)
	os.Exit(-1)
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;À la longue, ce style devient verbeux, répétitif et franchement pas agréable à lire.
&lt;/p&gt;&lt;p&gt;C’est là qu’on peut choisir une approche différente : factoriser la gestion d’erreur dans une fonction utilitaire qui se charge d’interrompre le programme dès qu’une erreur survient.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-50&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-50&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;func check(e error) {
	if e != nil {
		panic(fmt.Sprintf(&amp;quot;Erreur fatale : %v&amp;quot;, e))
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;L’idée est simple : à chaque fois qu’une fonction retourne une erreur que l’on considère bloquante, on appelle check(err).
&lt;/p&gt;&lt;p&gt;S’il n’y a rien à signaler, le programme continue.
&lt;/p&gt;&lt;p&gt;Sinon on déclenche un panic volontairement.
&lt;/p&gt;&lt;p&gt;Cela dit, cette manière de faire montre rapidement ses limites. Si une fonction interne appelle elle-même check(), elle pourra déclencher un panic que l’appelant n’attendait pas forcément. On se retrouve alors avec un mélange de fonctions &quot;sûres&quot; et d&#039;autres &quot;qui paniquent&quot; dans une même base de code.
&lt;/p&gt;&lt;p&gt;On s&#039;éloigne beaucoup trop de la philosophie du langage, qui nous donne pourtant un trio d&#039;outils très puissant :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;panic : pour déclencher une erreur irrécupérable
&lt;/li&gt;&lt;li&gt;defer : pour enregistrer une action à exécuter quoi qu’il arrive (cleanup, log, récupération…)
&lt;/li&gt;&lt;li&gt;recover : pour intercepter un panic et reprendre la main proprement
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;En les combinant, on peut factoriser la gestion d&#039;erreur tout en gardant un code propre.
&lt;/p&gt;&lt;blockquote&gt; Attention, cette approche n’est pas compatible avec tous les types de programmes.
&lt;br /&gt; Une API, un serveur, ou n’importe quel service censé tourner longtemps sans faire un caprice, ne devraient surtout pas utiliser cette méthode. Dans ces cas-là, on reste sur la gestion d’erreurs explicite de Go. C’est un peu plus verbeux, mais nettement plus sain.
&lt;br /&gt; Disons qu’il vaut mieux faire tomber une seule goroutine que de kill tout Netflix parce qu’un développeur PHP a décidé d’essayer Go :troll:
&lt;br /&gt;&lt;/blockquote&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-51&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-51&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;func loadConfig(path string) string {
	fmt.Println(&amp;quot;loadConfig:&amp;quot;, path)

	if _, err := os.Stat(path); err != nil {
		panic(fmt.Errorf(&amp;quot;impossible de charger le fichier %s : %w&amp;quot;, path, err))
	}

	return &amp;quot;mode=fast;version=1.2&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Lorsqu’un panic est lancé, il remonte toute la pile d’exécution et termine le programme.
&lt;/p&gt;&lt;p&gt;Pour l’intercepter proprement là où on en a besoin, on utilise recover :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-52&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-52&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;err := recover()
if err != nil {
	fmt.Println(&amp;quot;ERROR:&amp;quot;, err)
	os.Exit(-1)
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et pour que ce recover s’exécute automatiquement à la fin d’un bloc (par exemple au niveau de main) on le place dans un defer. Ce defer peut être global ou appliqué seulement à une section critique du programme.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-53&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-53&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;defer func() {
	if r := recover(); r != nil {
		fmt.Println(&amp;quot;Le programme a rencontré une erreur : &amp;quot;, r)
		os.Exit(-1)
	}
}()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On obtient ainsi l’équivalent d’un throw =&gt; catch =&gt; finally que l’on retrouve dans d’autres langages.
&lt;/p&gt;&lt;p&gt;Voici maintenant un exemple complet pour visualiser clairement le flux :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-54&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-54&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;package main

import (
	&amp;quot;fmt&amp;quot;
	&amp;quot;os&amp;quot;
	&amp;quot;strings&amp;quot;
)

func main() {
	// Defer global : capture tout panic provenant du programme
	defer func() {
		if r := recover(); r != nil {
			fmt.Println(&amp;quot;Le programme a rencontré une erreur : &amp;quot;, r)
			os.Exit(-1)
		}
	}()

	fmt.Println(&amp;quot;=== Début du programme ===&amp;quot;)

	cfg := loadConfig(&amp;quot;config.txt&amp;quot;)
	value := readValue(cfg, &amp;quot;mode&amp;quot;)
	result := computeResult(value)

	fmt.Println(&amp;quot;Résultat final:&amp;quot;, result)
	fmt.Println(&amp;quot;=== Fin normale du programme ===&amp;quot;)
}

func loadConfig(path string) string {
	fmt.Println(&amp;quot;loadConfig:&amp;quot;, path)

	if _, err := os.Stat(path); err != nil {
		panic(fmt.Errorf(&amp;quot;impossible de charger le fichier %s : %w&amp;quot;, path, err))
	}

	// on simule un contenu
	return &amp;quot;mode=fast;version=1.2&amp;quot;
}

func readValue(cfg, key string) string {
	fmt.Println(&amp;quot;readValue:&amp;quot;, key)

	parts := strings.Split(cfg, &amp;quot;;&amp;quot;)
	for _, p := range parts {
		if strings.HasPrefix(p, key+&amp;quot;=&amp;quot;) {
			return strings.TrimPrefix(p, key+&amp;quot;=&amp;quot;)
		}
	}

	panic(fmt.Errorf(&amp;quot;clé &amp;apos;%s&amp;apos; introuvable dans la config&amp;quot;, key))
}

func computeResult(mode string) string {
	fmt.Println(&amp;quot;computeResult:&amp;quot;, mode)

	if mode == &amp;quot;fast&amp;quot; {
		return &amp;quot;OK-FAST&amp;quot;
	}
	if mode == &amp;quot;slow&amp;quot; {
		return &amp;quot;OK-SLOW&amp;quot;
	}

	panic(fmt.Errorf(&amp;quot;mode &amp;apos;%s&amp;apos; inconnu&amp;quot;, mode))
}

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ici le defer est au tout début de la pile, donc dès qu&#039;il est déclenché, le programme se termine totalement. Si on place ce defer au début d&#039;une fonctionnalité critique, seule cette dernière tombera proprement en erreur et pas tout le programme.
&lt;/p&gt;&lt;p&gt;Merci à mon collègue Pierre de m&#039;avoir montré cette approche.
&lt;/p&gt;&lt;br /&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-12-05-exceptions-go.html" />
    
    <published>2025-12-05T16:19:36Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-09-11-oeuf-poule-homeassistant.html</id>
    <title type="html">De l'oeuf, de la poule ou de Home Assistant ?
</title>
    <updated>2025-09-11T14:50:09Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;De l'oeuf, de la poule ou de Home Assistant ?
&lt;/h1&gt;
        &lt;img alt=&quot;le visuel du dos du macbook pro qui fait tourner l&#039;instance de home assistant. il y a pleins de stickers geek dessus.&quot; src=&quot;https://darkblog.lhoir.me//assets/2025-09-11-oeuf-poule-homeassistant/le-serveur.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Je me définis comme un geek techno enthousiaste. J’aime l’idée que la technologie puisse nous simplifier la vie quotidienne. Et c’est dans ce sens que j’ai toujours été attiré par la domotique. Pouvoir piloter et programmer sa maison pour qu’elle fonctionne selon ses besoins est vraiment exaltant.
&lt;/p&gt;&lt;p&gt;Attention toutefois : être enthousiaste ne veut pas dire naïf. Utiliser la technologie, oui, mais seulement si elle est utile et proportionnée aux besoins du moment.
&lt;/p&gt;&lt;p&gt;Cela faisait des années que je pensais installer une instance de Home Assistant à la maison. Et, en même temps, cela faisait tout autant d’années que je me demandais si cela valait vraiment le coup. Ai-je assez de domotique chez moi pour que ce soit pertinent ? Est-ce plus pratique que d’utiliser les multiples applications fournies avec chaque appareil ?
&lt;/p&gt;&lt;p&gt;Être critique, c’est aussi essayer de ne pas céder aux sirènes de tous les constructeurs, qui veulent chacun imposer leur propre “pont” ou leur hub propriétaire. Souvent des boîtiers de marques chinoises, pas toujours fiables… Ce n’est pas évident à éviter, mais ce n’est pas non plus le sujet de cet article.
&lt;/p&gt;&lt;p&gt;C’est un peu grâce à la chaîne YouTube Abrège que je me suis vraiment remis à la domotique et à l’électronique, à bricoler avec des composants. En 2022, il a publié une vidéo expliquant comment créer une box domotique avec Home Assistant sur un Raspberry Pi, avec un peu d’électronique, d’impression 3D et un tutoriel complet d’installation et de configuration. Parfait : j’ai lancé de longues impressions sur ma Ender 3 de l’époque, pendant que j’installais Home Assistant sur un des Raspberry Pi qui prenaient la poussière chez moi.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/@Abr%C3%A8ge&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;La chaîne de Abrège
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=e7MKEdTGX1U&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;La vidéo de la box domotique Home assistant 2022
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je ne dirais pas que cette tentative a été un échec, mais plutôt que je m’y suis lancé sans trop réfléchir. Le Raspberry Pi était un peu vieux pour supporter la charge, et je n’avais finalement pas grand-chose à y connecter. Après quelques semaines, j’ai fini par tout retirer.
&lt;/p&gt;&lt;blockquote&gt; Au fond, la vraie question reste : par où commencer ? Faut-il empiler des gadgets domotiques avec leurs applis propriétaires pour les piloter, ou bien débuter directement par une instance de Home Assistant ?
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Je ne pense pas pouvoir donner une réponse claire et définitive à cette question, mais je peux au moins expliquer mon cheminement.
&lt;/p&gt;&lt;blockquote&gt; Home Assistant est une plateforme open source de domotique qui permet de centraliser, piloter et automatiser une maison connectée. L’idée est simple : au lieu d’utiliser une application différente pour chaque appareil (ampoules, chauffage, prises connectées, etc.), Home Assistant regroupe tout dans une seule interface. En plus de l’aspect pratique, il offre un énorme avantage : l’automatisation. On peut définir des règles intelligentes (“si la température descend en dessous de 18°C, allume le chauffage”, “si le soleil se couche, baisse les volets”), le tout sans dépendre du cloud de chaque constructeur. Bref, c’est un peu le tableau de bord et le cerveau de la maison connectée.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.home-assistant.io/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;site officiel de home-assistant
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Tout a commencé en 2014, avec un Raspberry Pi équipé d’un module caméra pour surveiller mes chats. Je ne voulais pas de solution “toute faite”, alors j’ai bricolé un petit système maison à base de raspistill et de scp pour envoyer les photos vers mon VPS. Je n’ai jamais voulu installer de caméra à l’intérieur; je trouve ça trop intrusif, surtout avec un micro. Du coup, un simple cron lançait des photos à intervalles réguliers. Pour la visualisation, une page toute bête mélangeant PHP et HTML, protégée par un .htaccess avec mot de passe. C’était basique, mais très stable… et ça fonctionne encore très bien aujourd’hui, même après plusieurs déménagements.
&lt;/p&gt;&lt;p&gt;Peu après, j’ai commencé à jouer avec des Philips Hue, notamment avec un détecteur de présence, ce qui m’a amené à installer le fameux pont Hue. Et puis... c’est resté en l’état pendant un bon moment. Enfin, c’est ce que je croyais : petit à petit, l’Apple TV s’est transformée en relais domotique pour les produits de la marque à la pomme. D’autres appareils sont aussi venus se greffer, qu’ils soient compatibles Bluetooth ou Zigbee. 
&lt;/p&gt;&lt;p&gt;En parallèle, j’ai continué mes petites bidouilles électroniques : j’ai ajouté des capteurs de température et d’humidité à mes modules caméra, et j’ai fait remonter ces nouvelles informations sur ma page PHP. Je crois que je continuais ainsi pour deux raisons : d’une part, garder la maîtrise de mon code ; d’autre part, l’espoir de faire plus qu’un simple affichage “instantané”. J’aurais aimé pouvoir naviguer dans les photos, remonter le temps et voir ce qui s’était passé dans la journée. Idem pour les températures : avoir un suivi sur la journée, comparer avec la semaine précédente ou l’année passée...
&lt;/p&gt;&lt;p&gt;Mais vous savez quoi ? Encore aurait-il fallu coder tout cela. Et comme je n’ai a priori pas trouvé le temps de m’y mettre, on peut traduire “pas eu le temps” par : ces fonctionnalités ne méritaient sans doute pas d’y consacrer autant d’efforts.
&lt;/p&gt;&lt;p&gt;La seule amélioration que je pense encore réaliser, car relativement simple à développer, serait de créer une vidéo à partir des photos du jour. Si possible en combinant les différents points de vue dans une même vidéo. Ce ne serait pas trop compliqué non plus d’afficher automatiquement, chaque jour, la vidéo de la veille dans Home Assistant.
&lt;/p&gt;&lt;p&gt;Cette réflexion, c’est celle que j’ai aujourd’hui sur mon cheminement, et c’est ce qui explique mon échec avec Home Assistant en 2022 : je n’étais pas prêt à me reposer sur ce “tiers” pour l’affichage de ma domotique. J’avais l’impression de devoir faire trop de compromis pour faire rentrer mon usage dans celui de l’instance. 
&lt;/p&gt;&lt;p&gt;Et puis, en voyant des installations Home Assistant chez des amis ou sur la chaîne Abrège, mon avis a changé, et donc mon usage aussi. Finalement, je me suis rendu compte que je n’avais rien à faire de la “course aux statistiques” (la preuve avec ce blog, totalement statique et sans traqueur). Ce que je voulais surtout, c’était ne plus me baser sur une box vaguement imprimée en 3D ni sur un Raspberry Pi qui aurait vite montré ses limites.
&lt;/p&gt;&lt;p&gt;Je n’avais pas non plus envie d’acheter un Raspberry Pi 5 uniquement pour gagner en performances. D’autant que j’ai déjà une bonne réserve de matériel à la maison ; l’équivalent électronique de la fameuse “boîte à rabiots” de l’époque Warhammer 40K, sans doute.
&lt;/p&gt;&lt;p&gt;J’avais déjà migrer ce MBP vers Ubuntu à l’époque où Apple avait cessé d’en assurer la prise en charge. La seule difficulté, en réalité, a été de me souvenir de comment booter sur une clé USB sur un Mac.
&lt;/p&gt;&lt;blockquote&gt; Pour booter sur une clé USB sur Mac, il faut maintenir la touche Option (alt) au démarrage, puis choisir le périphérique à lancer.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Avec cette nouvelle installation, j’ai découvert que mon système de chauffage (les têtes thermostatiques connectées) était automatiquement reconnu, tout comme certains autres appareils de la maison. Parfait : dès l’installation, j’avais déjà un visuel vraiment utile.
&lt;/p&gt;&lt;p&gt;Restait alors à intégrer mes prises de photos dans cette instance. Et là, c’est le développeur un peu plus expérimenté qui a pris le dessus : MQTT m’a semblé être la solution la plus simple et la plus efficace à mettre en place.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; MQTT à la rescousse de la bidouille domotique
&lt;/h2&gt;&lt;p&gt;MQTT (Message Queuing Telemetry Transport) est un protocole de messagerie léger, pensé à l’origine pour les objets connectés. Son principe est simple : des capteurs ou programmes publient des messages sur des “topics” (un peu comme des canaux), et d’autres systèmes peuvent s’y abonner pour les recevoir. Dans mon cas, c’était parfait : mes scripts maison pouvaient publier les données de mes capteurs (photos, température, humidité, etc.), et Home Assistant se chargeait de les récupérer et de les afficher. Pas besoin de recoder toute une interface, je gardais mes bidouilles côté Raspberry/serveur, et je laissais Home Assistant faire ce qu’il sait très bien faire : centraliser et présenter l’information.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/MQTT&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;https://fr.wikipedia.org/wiki/MQTT
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://mqtt.org/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le site officiel de MQTT
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Pour l’intégration de Home Assistant avec mes caméras, j’ai créé un utilisateur par Raspberry Pi dans HA : un login, un mot de passe, et surtout une connexion exclusivement en local.
&lt;/p&gt;&lt;p&gt;Ensuite, j’ai installé le Mosquitto broker via :
&lt;/p&gt;&lt;blockquote&gt; Paramètres &gt; Modules complémentaires &gt; Boutique des modules complémentaires.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Lors de l’installation, pensez à activer le lancement au démarrage, ainsi que l’option “chien de garde” qui relance automatiquement le service en cas de panne.
&lt;/p&gt;&lt;p&gt;Enfin, dans :
&lt;/p&gt;&lt;blockquote&gt; Paramètres &gt; Appareils et services &gt; MQTT &gt; (roue crantée) &gt; Configurer les options MQTT
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;...vérifiez que la découvrabilité est activée et que le préfixe de découverte est homeassistant. (Si vous le changez, adaptez bien les extraits de code ci-dessous.)
&lt;/p&gt;&lt;p&gt;Sur chacun de mes Raspberry Pi, j’ai installé le client MQTT :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-44&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-44&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;sudo apt install -y mosquitto-clients
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ensuite, dans le code qui prend chaque capture d’écran, j’ajoute la publication du topic de configuration :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-45&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-45&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;mosquitto_pub -r -h IP_MQTT -u USER_MQTT -P PWD_MQTT \
-t &amp;quot;homeassistant/camera/camera_name/config&amp;quot; \
-m &amp;apos;{
    &amp;quot;name&amp;quot;: &amp;quot;My Cam&amp;quot;,
    &amp;quot;unique_id&amp;quot;: &amp;quot;MY_UNIQUE_ID_CAM&amp;quot;,
    &amp;quot;topic&amp;quot;: &amp;quot;cams/camera_name/image&amp;quot;,
    &amp;quot;device&amp;quot;: {
      &amp;quot;identifiers&amp;quot;: [&amp;quot;cam_name_pi&amp;quot;],
      &amp;quot;name&amp;quot;: &amp;quot;Cam Name Pi&amp;quot;,
      &amp;quot;model&amp;quot;: &amp;quot;Raspberry Pi Cam&amp;quot;,
      &amp;quot;manufacturer&amp;quot;: &amp;quot;DIY&amp;quot;
    }
  }&amp;apos;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Voici les explication des options de la commande : 
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;-r retain flag : le message est conservé par le broker, ce qui permet aux nouveaux clients qui s’abonnent de recevoir immédiatement la config.
&lt;/li&gt;&lt;li&gt;-h adresse de ton broker MQTT.
&lt;/li&gt;&lt;li&gt;-u et -P identifiants (login/mot de passe).
&lt;/li&gt;&lt;li&gt;-t le topic (ici la configuration de la caméra).
&lt;/li&gt;&lt;li&gt;-m le message JSON publié (décrit la caméra à Home Assistant).
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Je ne sais pas pourquoi mon instance de Home Assistant n’enregistre pas correctement cette configuration (malgré le -r). Pour éviter tout souci, je renvoie donc la config à chaque fois. Je ne pense pas que cela alourdisse démesurément la charge sur HA… et pour l’instant, ça passe.
&lt;/p&gt;&lt;p&gt;À partir de là, vous devriez retrouver votre caméra dans les entités de Home Assistant. Cette entité pourra ensuite être utilisée dans vos tableaux de bord pour l’affichage.
&lt;/p&gt;&lt;p&gt;Enfin, pour envoyer l’image générée par raspistill ou rpicam-still, je publie directement le fichier sur le topic image :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-46&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-46&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;mosquitto_pub -h &amp;quot;$MQTT_BROKER&amp;quot; -u &amp;quot;$MQTT_USER&amp;quot; -P &amp;quot;$MQTT_PWD&amp;quot; \
-t &amp;quot;$MQTT_TOPIC&amp;quot; -f &amp;quot;$PATH_TO_FILE/$FILE&amp;quot; -q 1
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;-f envoie directement le contenu d’un fichier (ici, l’image).
&lt;/li&gt;&lt;li&gt;-q 1 qualité de service : l’assure que le message est délivré au moins une fois.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Pour l&#039;envoi de texte comme la température ou l&#039;humidité voici une requête valide :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-47&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-47&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;mosquitto_pub -r -h &amp;quot;$MQTT_BROKER&amp;quot; -u &amp;quot;$MQTT_USER&amp;quot; -P &amp;quot;$MQTT_PWD&amp;quot; \
  -t &amp;quot;homeassistant/sensor/my_temp_sensor/config&amp;quot; \
  -m &amp;apos;{
    &amp;quot;name&amp;quot;: &amp;quot;Temperature&amp;quot;,
    &amp;quot;unique_id&amp;quot;: &amp;quot;my_temp_sensor&amp;quot;,
    &amp;quot;state_topic&amp;quot;: &amp;quot;sensors/temperature_sensor/state&amp;quot;,
    &amp;quot;value_template&amp;quot;: &amp;quot;{{ value_json.temp }}&amp;quot;,
    &amp;quot;unit_of_measurement&amp;quot;: &amp;quot;°C&amp;quot;,
    &amp;quot;device_class&amp;quot;: &amp;quot;temperature&amp;quot;,
    &amp;quot;state_class&amp;quot;: &amp;quot;measurement&amp;quot;
  }&amp;apos;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Avec cette mise en place, j’ai enfin trouvé un équilibre entre mes bidouilles maison et la puissance de Home Assistant. MQTT agit comme une passerelle idéale : mes scripts continuent de tourner comme je les aime, et Home Assistant se charge d’unifier, d’afficher et de rendre tout ça utilisable au quotidien.
&lt;/p&gt;&lt;p&gt;Avec un peu de pratique, je pense exploiter bien mieux les possibilités de MQTT; notamment dans l’autre sens : par exemple, avoir un bouton dans Home Assistant pour forcer la prise de vue sur un des Raspberry Pi.
&lt;/p&gt;&lt;p&gt;Pour l’instant, je m’amuse surtout à générer du contenu en lecture seule via mes scripts maison. Mais un script particulier mérite bien un article à lui seul : il concerne la seconde phase de l’amélioration de mon cabanon. Et cette fois-ci, on s’attaquera à un projet plus ambitieux côté électronique, avec un relais et un D1 mini comme cerveau des opérations (et lien avec Home Assistant)… le tout sans ESPHome, parce que sinon ce serait trop facile.
&lt;/p&gt;&lt;p&gt;Et pour celles et ceux qui auraient manqué le début de cette histoire de cabanon :
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2025-07-28-le-cabanon.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Premier article sur le cabanon
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-09-11-oeuf-poule-homeassistant.html" />
    
    <published>2025-09-11T14:50:09Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-07-28-le-cabanon.html</id>
    <title type="html">Le cabanon
</title>
    <updated>2025-07-28T17:06:38Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Le cabanon
&lt;/h1&gt;
        &lt;img alt=&quot;&quot; src=&quot;https://darkblog.lhoir.me//assets/2025-07-28-le-cabanon/cover.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Cet été, c’est décidé : je m’occupe enfin du cabanon au fond du jardin.
&lt;/p&gt;&lt;p&gt;Pas question de tout rénover (même s’il en aurait bien besoin), mais plutôt de lui offrir un petit level up bien mérité. L’idée, c’est surtout d’avoir des projets concrets à réaliser… et donc des articles à écrire et partager ici. 
&lt;/p&gt;&lt;p&gt;A priori, ce sera une mini-série en trois volets ; celui que vous êtes en train de lire étant le premier.
&lt;/p&gt;&lt;p&gt;Phase 1 : désencombrer et sécuriser l’électricité. On commence par du concret : vider l’espace et remettre un peu d’ordre dans l’installation électrique existante. Beaucoup de photos au programme, ce qui change un peu de mes articles habituels, même si le format du blog n’est pas forcément pensé pour ça.
&lt;/p&gt;&lt;p&gt;Phase 2 : fabriquer une VMC un peu maligne. Je vais tenter de bricoler une VMC en mode Do It Yourself, avec une petite dose d’intelligence, et peut-être même une connexion à distance. 
&lt;/p&gt;&lt;p&gt;Phase 3 : une touche de domotique. Si le temps me le permet, j’ajouterai un capteur température/humidité pour l’extérieur, avec des leds de couleurs pour &quot;lire&quot; les infos depuis la maison,  relié à terme à une instance de Home Assistant, que je n&#039;ai pas encore. Juste ce qu’il faut pour commencer à domotiser le cabanon.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/cabanon_origine.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/cabanon_origine.png&quot; alt=&quot;L&#039;intérieur du cabanon peu après notre arrivée dans la maison
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Désencombrement
&lt;/h2&gt;&lt;p&gt;Il y a quelques semaines, j’ai attaqué la première étape : faire le grand vide dans le faux plafond du cabanon.
&lt;/p&gt;&lt;p&gt;Avec le temps, j’y avais entassé un joyeux mélange de trucs « au cas où » ; des objets sans vraie utilité mais qu’on garde parce qu’on a la place. Et quand on fait ça, on se retrouve avec un plafond saturé, un espace devenu inaccessible.. et aucun accès pour réparer la ventilation mécanique qui faisait un vacarme pas possible.
&lt;/p&gt;&lt;p&gt;J’ai donc sorti la visseuse, retiré les plaques d’OSB une à une… et voilà ce que ça donnait une fois tout mis à nu :
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/sans-faux-plafond.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/sans-faux-plafond.jpg&quot; alt=&quot;Vue de l’intérieur du cabanon sans les plaques d’OSB : une sensation de grand volume retrouvée.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;J&#039;ai également retirer les clous qu&#039;il y avait un peu partout sur la structure. Certains servaient à maintenir le câble du plafonier...
&lt;/p&gt;&lt;p&gt;Tant qu’à faire, j’ai aussi démonté proprement l’ancienne ventilation. Elle ne servait plus à grand-chose à part faire trembler les murs à chaque mise en route. Elle était directement câblée sur un disjoncteur dédié, pour faire office d&#039;interrupteur.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/l-ancienne-ventilation.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/l-ancienne-ventilation.jpg&quot; alt=&quot;C&#039;était donc ca qui faisait autant de bruit ? Notez le joli sucre pour relier ca directement au disjoncteur donc au 220v sans boite de dérivation.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt; On débranche tout
&lt;/h2&gt;&lt;p&gt;Et puisque l’on parle d’électricité… voici le fameux tableau qui me hante depuis notre arrivée dans cette maison :
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/tableau-de-la-mort.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/tableau-de-la-mort.jpg&quot; alt=&quot;Un tableau electrique nu, dans un cabanon, sans isolation rien... normal, tout va bien
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt; ⚠️ Avant d’aller plus loin, petit rappel important : L’électricité peut être dangereuse, voire mortelle.  
&lt;br /&gt; Ne mettez jamais les mains dans une installation sans avoir coupé l’alimentation générale, et uniquement si vous êtes sûr de ce que vous faites.  
&lt;br /&gt; En cas de doute, n’hésitez jamais à faire appel à un professionnel qualifié, que ce soit pour un conseil ou un coup de main.  
&lt;br /&gt; Et si vous choisissez malgré tout de faire les travaux vous-même, gardez ceci en tête :  
&lt;br /&gt; Si vous avez un doute… c’est qu’il n’y a aucun doute : vous ne savez pas.  
&lt;br /&gt; Dans ce cas, on arrête tout, on respire, et on demande de l’aide.  
&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Seconde note importante : je ne suis pas un professionnel. Cet article n’est pas un tutoriel à suivre à la lettre, mais simplement le récit d’un projet personnel, raconté à ma façon. Il est probable que certaines choses ne soient pas parfaitement conformes aux règles de l’art, même si j’essaie toujours d’appliquer un minimum de bon sens, notamment en matière de sécurité.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Rien ne va dans cette installation. Les câbles sont à nu, sans protection, exposés à l’intérieur du cabanon comme s’il ne pleuvait jamais en France (ou que la chaleur, et donc l’humidité dans une cabane en bois, ne pouvaient jamais grimper en flèche). L’alimentation générale, venant de la maison, est directement accessible et n’offre aucune protection des personnes. Evidemment, rien n’est étiqueté, les circuits lumière et prises sont mélangés allègrement, et les sections de câble sont pour le moins hasardeuses.
&lt;/p&gt;&lt;p&gt;Avant de tout couper, j’ai commencé par repérer soigneusement chaque circuit. Pour ça, j’ai d’abord coupé le différentiel et tous les disjoncteurs. Ensuite, je les ai remis un par un pour voir ce qui se passait (tout en gardant les doigts loin, bien sûr), puis je les ai redéclenchés pour étiqueter les câbles à froid.  
&lt;/p&gt;&lt;p&gt;Une fois tout repéré, j’ai coupé le départ dans la maison depuis le tableau principal. J’ai vérifié avec un tournevis testeur (vous savez, celui qui s’allume quand il y a du jus) que tout était bien hors tension. À partir de là, j’ai pu démonter proprement : les disjoncteurs, les peignes, les câbles, les restes du coffret, et même les plaques d’OSB autour.
&lt;/p&gt;&lt;p&gt;Et là encore, je suis allé de surprise en surprise. Le câble de terre, par exemple, passait derrière la cloison. Il était peint, usé, et noirci par l’oxydation là où il rejoignait le piquet. Super rassurant. Quant à l’alimentation générale, je pensais qu’elle allait directement jusqu’au coffret principal... Mais pourquoi faire simple et sécurisé ?
&lt;/p&gt;&lt;p&gt;Elle passait par un vieux boîtier de dérivation caché dans le mur, poussiéreux et fissuré. Les gaines des câbles étaient coupées avant de rentrer dans le boîtier. À l’intérieur, trois énormes sucres (ou dominos), bien tassés, reliés à des câbles rigides comme du fer à béton, et bien sûr dans un branchement en &quot;i&quot; (je ne sais pas si c’est le vrai terme), donc avec le câble d’arrivée et de départ du même côté du domino. Le câbles de terre que l&#039;on voit sur la photo n&#039;était pas relié au tableau final... Le seul point positif est qu&#039;il n&#039;y avait probablement pas assez d&#039;oxygène dedans pour un départ de feu.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/les-absurdites.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/les-absurdites.jpg&quot; alt=&quot;Trois photos d’illustration du paragraphe précédent, avec le câble de terre, et le boîtier d’alimentation fermé et ouvert.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Le plus dingue, c’est que pour pouvoir nous vendre la maison, les anciens propriétaires ont dû faire passer un professionnel pour vérifier l’installation électrique. Le seul défaut indiqué sur le rapport ?
&lt;/p&gt;&lt;blockquote&gt; Une ampoule pendante dans le dressing.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Sans commentaire.
&lt;/p&gt;&lt;p&gt;Dernière découverte : ce nid derrière le mur. Une sorte de cocon à la paroi très fine, comme du papier ou de la boue très sèche. Je ne suis pas fan des nids de bestioles comme ça, alors je n’ai pas trop réfléchi : après une rapide photo souvenir, je l’ai retiré sans tarder. Par chance, il était vide. Je ne suis pas certain de l’espèce qui l’a construit, peut-être des guêpes maçonnes (et là, c’est dommage, vu qu’elles sont utiles pour réguler les populations de nuisibles), ou bien des frelons… ce qui m’aurait nettement moins plu.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/nid.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/nid.jpg&quot; alt=&quot;Un nid, en sphères très fines comme du papier, caché dans le mur.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt; Et je remets le sooooon (enfin l&#039;electricité)
&lt;/h2&gt;&lt;p&gt;J’ai trouvé tout le matériel dans un magasin de bricolage près de chez moi, une enseigne rouge, noire et blanche pour ne pas les citer. Au total, j’en ai eu pour environ 50 euros. Par chance, les disjoncteurs et le différentiel étaient encore en bon état, ce qui a allégé la facture de remise à niveau. Il me restait aussi du câble provenant d’anciens travaux. J’ai surtout acheté :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;le nouveau coffret étanche,
&lt;/li&gt;&lt;li&gt;un câble de terre en 16mm²,
&lt;/li&gt;&lt;li&gt;de nouveaux peignes
&lt;/li&gt;&lt;li&gt;des tubes, des accroches…
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;J’ai commencé par installer le boîtier. Étanche, une seule ligne, mais ici, c’est largement suffisant. Je l’ai placé juste au-dessus de l’arrivée de l’alimentation générale, qui vient du sol. Le câble de terre est un peu plus long qu&#039;auparavent mais rien de bien méchant.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/boitier-en-cours.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/boitier-en-cours.jpg&quot; alt=&quot;Photo du câblage en cours dans le boitier. Je ne suis pas un pro, je fais ce que je peux.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;En parlant de la terre : j’avais d’abord pensé utiliser une grosse tresse de cuivre, comme celles qu’on emploie pour relier plusieurs piquets de terre entre eux ou vers un bornier de mise à la terre (entre le sous-sol et le tableau électrique). Mais en essayant de la fixer dans le bornier du coffret, je me suis rendu compte que je galérais à faire tenir le tout correctement.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/terre-dangereuse.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/terre-dangereuse.jpg&quot; alt=&quot;Ne faites jamais ce genre de branchement de terre, c&#039;est interdit, il y a un risque d&#039;échauffement
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Et comme souvent dans ces cas-là : s’il y a un doute, c’est qu’il n’y a pas de doute, j’étais en train de faire une belle bêtise.
&lt;/p&gt;&lt;p&gt;Je suis donc retourné au magasin pour demander conseil. (Après avoir également demandé à mon papa ancien electricien dans les trains) Le vendeur, après avoir vu la photo de mon bidouillage, m’a confirmé qu’il est strictement interdit de faire ce genre de branchement. Une liaison mal adaptée, surtout avec une section trop importante mal serrée, peut chauffer dangereusement en cas de fuite de courant.
&lt;/p&gt;&lt;p&gt;J&#039;ai opté pour le cable de 16mm2, sur les conseils du vendeur. J&#039;ai un peu galéré à l&#039;accrocher sur le bornier du boitier, mais en divisant les conducteurs en deux ça passe. J&#039;ai protégé mon branchement avec une gaine thermo, au cas où.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/terre-ok.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/terre-ok.jpg&quot; alt=&quot;Le cblage de la terre dans le boitier avec de la gaine thermo pour protéger les conducteurs.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Même si c’est super frustrant de devoir sacrifier une partie de ce qu’on n’utilise pas, il ne faut surtout pas laisser de métal visible ou accessible une fois les peignes en place. Le bon réflexe :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;retirer la gaine plastique pour pouvoir couper le métal à ras de la dernière patte utilisée,
&lt;/li&gt;&lt;li&gt;puis recouper la partie plastique un peu plus longue que nécessaire, afin de recouvrir complètement l’extrémité et éviter tout risque de contact accidentel.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Ce n’est pas forcément joli… mais c’est beaucoup plus sûr.
&lt;/p&gt;&lt;p&gt;J’ai conservé le différentiel et les disjoncteurs d’origine, donc je ne me suis pas trop pris la tête sur le dimensionnement précis de la ligne. J’ai simplement mis les prises de courant et la partie domotique sur deux disjoncteur 16A, juste après le différentiel, puis j’ai mis les éclairages sur deux 10A (un éclairage intérieur et un extérieur). Il y a sûrement moyen de faire mieux ou plus optimisé, mais ça me semble correct dans le contexte du cabanon.
&lt;/p&gt;&lt;p&gt;J’ai pas mal galéré à refaire tous les circuits, à placer correctement les câbles pour éviter que tout s’emmêle. Mais au final, je suis plutôt fier du résultat. J’ai tout étiqueté proprement : aussi bien sur le tableau que sur les boîtes de dérivation. J’ai également recâblé la lumière intérieure, que j’ai passée dans un tube PVC pour un rendu plus propre. La gaine générale et le câble de terre passent eux aussi dans des tubes PVC, et j’ai même ajouté du scotch jaune et vert à intervalles réguliers pour bien identifier le fil de terre. Cet identification n&#039;était pas nécessaire, elle était donc indispensable :).
&lt;/p&gt;&lt;p&gt;Pour finir, j’ai profité d’avoir entièrement vidé le cabanon pour refaire les cloisons en OSB, en recyclant les plaques que j’avais retirées du faux plafond.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/resultat-final.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-07-28-le-cabanon/resultat-final.jpg&quot; alt=&quot;C&#039;est beau, c&#039;est propre, c&#039;est tout étiqueté...
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;J’y ai passé bien plus de temps que prévu : les allers-retours au magasin, les surprises au fil du chantier, les câbles de grosse section à dénuder à la main (une joie)... Au final, ce projet s’est étalé sur 3 à 4 jours, en y travaillant de manière non continue.
&lt;/p&gt;&lt;p&gt;C’était un sacré morceau pour une « simple » mise en sécurité. Mais maintenant, le cabanon est sain, fonctionnel, et prêt pour la suite.
&lt;/p&gt;&lt;p&gt;Prochaine étape : lui redonner un peu de souffle... avec une &quot;VMC&quot; faite maison !&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-07-28-le-cabanon.html" />
    
    <published>2025-07-28T17:06:38Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-06-06-notifications-sms-free.html</id>
    <title type="html">Un système de notification par SMS
</title>
    <updated>2025-06-06T15:27:17Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Un système de notification par SMS
&lt;/h1&gt;
        &lt;img alt=&quot;Logo du projet NotiFreeMe où l&#039;on peut voir la mascotte du langage Go avec une notification et le nom du projet ecrit en blanc sur fond bleu, sauf le mot Free qui est en rouge comme le logo de la marque&quot; src=&quot;https://darkblog.lhoir.me//assets/2025-06-06-notifications-sms-free/logo.png&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Ce week-end, j’ai découvert une option bien pratique grâce à un contact : Free Mobile propose un service gratuit de notifications par SMS inclus avec ses abonnements. Ce service vous permet de vous envoyer des SMS depuis vos scripts ou applications, idéal pour être alerté d’un événement système ou recevoir un rapport automatique.
&lt;/p&gt;&lt;p&gt;Si vous êtes abonné Free Mobile, l’activation se fait via l’espace abonné (depuis un navigateur, pas l’application mobile) : Mon forfait Mobile &gt; Mes options &gt; Notifications par SMS.
&lt;/p&gt;&lt;p&gt;Une fois activé, une clé d’API privée est générée.
&lt;/p&gt;&lt;blockquote&gt; ⚠️ Ne la partagez avec personne, elle donne un accès direct à l’envoi de SMS vers votre ligne.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-06-06-notifications-sms-free/activation-option.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-06-06-notifications-sms-free/activation-option.png&quot; alt=&quot;Activation de l&#039;option sur le site de free
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Sur le site, vous trouverez toutes les explications pour utiliser cette API de notifications, et cela m&#039;a donné pas mal d&#039;idées d&#039;utilisation (eux parlent de NAS ou de systèmes d&#039;alarme). Je vais intégrer ces notifications à mes différents scripts et notamment à GoKeep.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2025-05-27-live-blog-coding-et-golang.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Live blog coding et amusement en golang
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Fonctionnement de l&#039;API de Free
&lt;/h2&gt;&lt;p&gt;Pour envoyer un SMS avec le système de notification, il suffit de faire une requete POST ou GET à cette adresse
&lt;/p&gt;&lt;blockquote&gt; https://smsapi.free-mobile.fr/sendmsg
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Avec les paramètres suivants:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;user : Votre identifiant Free mobile
&lt;/li&gt;&lt;li&gt;pass : La clef d&#039;API générée par Free, celle ci est regénérée à chaque fois que vous désactivez et réactivez l&#039;option
&lt;/li&gt;&lt;li&gt;msg : Le message que vous voulez vous envoyer, en encodage url (Percent-encoding)
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Enfin, je n&#039;ai jamais réussi à utiliser POST, je ne sais pas si la documentation est à jour.
&lt;/p&gt;&lt;blockquote&gt; Par exemple : https://smsapi.free-mobile.fr/sendmsg?user=12345689&amp;pass=KeyANePAsPArtager&amp;msg=Hello%20World%20! 
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Dans tous les cas, on profite des codes retours HTTP pour comprendre ce qui s&#039;est passé :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;200 : Le SMS a été envoyé sur votre mobile.
&lt;/li&gt;&lt;li&gt;400 : Un des paramètres obligatoires est manquant.
&lt;/li&gt;&lt;li&gt;402 : Trop de SMS ont été envoyés en trop peu de temps.
&lt;/li&gt;&lt;li&gt;403 : Le service n&#039;est pas activé sur l&#039;Espace Abonné, ou login / clé incorrecte.
&lt;/li&gt;&lt;li&gt;500 : Erreur côté serveur. Veuillez réessayer ultérieurement.
&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt; NotiFreeMe
&lt;/h2&gt;&lt;p&gt;Pour simplifier l’intégration dans mes projets, j’ai commencé à écrire NotiFreeMe, une petite bibliothèque en Go. Elle permet d’envoyer facilement des SMS via l’API Free sans avoir à réécrire tout à chaque fois.
&lt;/p&gt;&lt;blockquote&gt; Golang est particulièrement adapté à ce genre de projet : rapide, statique, déployable en un binaire. Et comme souvent : un besoin + une bonne excuse = un projet 😄
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Commençons avec un code minimaliste.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-42&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-42&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;package main

import (
	&amp;quot;fmt&amp;quot;
	&amp;quot;net/http&amp;quot;
	&amp;quot;net/url&amp;quot;
)

func sendNotifree(user string, pass string, message string) error {
	apiURL := &amp;quot;https://smsapi.free-mobile.fr/sendmsg&amp;quot;
    params := url.Values{}
    params.Add(&amp;quot;user&amp;quot;, user)
    params.Add(&amp;quot;pass&amp;quot;, pass)
    params.Add(&amp;quot;msg&amp;quot;, message)

    resp, err := http.Get(apiURL + &amp;quot;?&amp;quot; + params.Encode())
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != 200 {
        return fmt.Errorf(&amp;quot;échec de l&amp;apos;envoi SMS: HTTP %d&amp;quot;, resp.StatusCode)
    }

    return nil
}

func main() {
	user := &amp;quot;NUMERO_CLIENT&amp;quot;
	pass := &amp;quot;CLEF_API&amp;quot;
	message := &amp;quot;[NotiFreeMe] Hello, World !&amp;quot;

	err := sendNotifree(user, pass, message)
    if err != nil {
        fmt.Println(&amp;quot;Erreur :&amp;quot;, err)
    } else {
        fmt.Println(&amp;quot;SMS envoyé avec succès !&amp;quot;)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ce code a le mérite de fonctionner, mais il est loin d’être réutilisable. Mon objectif est d’aller plus loin : je veux que NotiFreeMe puisse aussi bien être utilisé comme une dépendance dans d’autres outils en Go, que comme un exécutable indépendant, utilisable par n’importe quel script, quel que soit le langage. Encore une fois, la force de Go est de produire un exécutable autonome, sans dépendances.
&lt;/p&gt;&lt;p&gt;J’ai avancé pas à pas vers cet objectif, en m’aidant de ChatGPT et du Chat de Mistral. Oui, j’utilise des LLM pour m’accompagner dans le développement de mes solutions et non, je n’en ai pas honte. J’en reparlerai un peu plus tard.
&lt;/p&gt;&lt;p&gt;C&#039;est ainsi que je suis arrivé à une première version stable et simple de NotiFreeMe, disponible sur Gitlab:
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://gitlab.com/dark-open/notifreeme&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;NotiFreeMe, une dépendance et un outil autonome pour envoyer des notifications SMS via Free Mobile.
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Intégration dans GoKeep
&lt;/h2&gt;&lt;p&gt;Ce que j&#039;aimerai améliorer dans GoKeep c&#039;est l&#039;ajout de notifications par SMS selon des événements :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Lorsque mon adresse IP a changé
&lt;/li&gt;&lt;li&gt;Lorsque les DNS ont été mis à jour
&lt;/li&gt;&lt;li&gt;Lorsque le script plante lamentablement avec un panic(e)
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Première étape, je code un truc simple : j&#039;importe la dépendance NotiFreeMe, j&#039;ajoute les champs user et pass à ma structure Settings, je crée le client et j&#039;envoie les messages. Je teste en local avec succès, et je déploie rapidement en production.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-43&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-43&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;import &amp;quot;gitlab.com/dark-open/notifreeme/notiFreeMe&amp;quot;

type Settings struct {
    ApplicationKey    string   `json:&amp;quot;applicationKey&amp;quot;`
    ApplicationSecret string   `json:&amp;quot;applicationSecret&amp;quot;`
    ConsumerKey       string   `json:&amp;quot;consumerKey&amp;quot;`
    Domains           []Domain `json:&amp;quot;domains&amp;quot;`
    FreeUser string     `json:freeUser`
    FreePass string `json:freePass`
}

func main() {
    [...]
    freeClient,errFree := notiFreeMe.NewClient(settings.FreeUser, settings.FreePass)
    if (nil == errFree) {
        err = freeClient.Send(&amp;quot;[GoKeep] Nouvelle IP : &amp;quot; + currentIp)
        if nil != err {
            log.Println(&amp;quot;Fail to send SMS&amp;quot;)
        }
    } else {
        log.Println(&amp;quot;Erreur lors de la création du client Free&amp;quot;)
    }
    [...]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;C&#039;est fonctionnel, mais ce code est loin d&#039;être optimal :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Le script est maintenant fortement couplé à l’envoi des notifications SMS (dans .godnsfile)
&lt;/li&gt;&lt;li&gt;L’envoi des notifications bloque le reste du code
&lt;/li&gt;&lt;li&gt;Je ne peux pas déclencher de notification facilement depuis ma fonction check()
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Encore une fois, j&#039;ai appliqué ces contraintes une à une à mon code en m&#039;aidant des IA. Au final, j&#039;ai un code plutôt lisible, qui utilise les goroutines et les channels pour paralléliser l’envoi des notifications.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Je connaissais ces concepts de Go de nom, mais je n’avais encore jamais eu l’occasion de les mettre en pratique. Et comme pour toutes les premières fois, cela fait un peu peur : on ne sait pas vraiment par où commencer. Avoir un coup de main (même d’une IA) pour appliquer ces notions sur un projet personnel me semble vraiment formateur. On n’a pas toujours la chance d’avoir un développeur senior sous la main pour nous aider.
&lt;/p&gt;&lt;p&gt;Maintenant que je les ai abordés grâce à l’IA, est-ce que je maîtrise ces concepts ? Absolument pas. Mais j’ai désormais une base de code que je comprends parfaitement, et qui me permet de poursuivre leur apprentissage sereinement, en évitant de bloquer sur des &quot;panic: deadlock&quot; incompréhensibles dans la console.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Le système de notifications est désormais optionnel, en passant par un second fichier de configuration (.freecreds), et son initialisation est déclenchée très tôt dans l’exécution du programme. Cela rend le mécanisme totalement découplé : même si le fichier .freecreds est absent ou invalide, le reste du script continue de fonctionner normalement.
&lt;/p&gt;&lt;p&gt;Enfin, ces améliorations m’ont permis d’initialiser la goroutine et le client SMS dès le démarrage, ce qui, combiné au caractère optionnel du système, permet à la fonction check() de tenter un envoi de SMS sans risque de crash.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://gitlab.com/dark-open/gokeep&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Dépôt de GoKeep sur Gitlab
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;J’allais enchainer avec mon rapport aux IA (ou LLM… enfin vous voyez quoi). Mais en y réfléchissant, j’ai tellement de choses à dire sur le sujet, entre usage perso, pro, quotidien, et bidouilles en tout genre... impossible pour moi de résumer tout cela dans un seul pauvre petit paragraphe.
&lt;/p&gt;&lt;p&gt;J&#039;évite donc de faire une énorme digression du sujet principal et je vous invite à surveiller mon flux RSS pour ne pas rater la sortie de ce futur article. Stay tuned !
&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-06-06-notifications-sms-free.html" />
    
    <published>2025-06-06T15:27:17Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-05-27-live-blog-coding-et-golang.html</id>
    <title type="html">Live blog coding et amusement en golang
</title>
    <updated>2025-06-02T11:43:09Z</updated>

    <author>
        <name></name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Live blog coding et amusement en golang
&lt;/h1&gt;
        &lt;img alt=&quot;Une représentation graphique de Teal&#039;c et le colonel O&#039;Neil devant la porte des étoiles avec le vortex ouvert. Le colonel fait du golf. Image génrée par IA&quot; src=&quot;https://darkblog.lhoir.me//assets/live-blog-coding-et-golang/cover.png&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;On dit souvent que pour se motiver à lancer (et surtout finir) un projet, le mieux c’est de le faire en live, avec du public. Apparemment, ça pousse à aller jusqu’au bout. C’est en tout cas ce que je remarque chez pas mal de devs-influenceurs que je suis sur YouTube.
&lt;/p&gt;&lt;p&gt;Bon, moi j’ai clairement pas leur audience et spoiler : je compte pas me filmer en train de coder pendant 3 heures.
&lt;/p&gt;&lt;p&gt;Du coup, j’ai eu une idée qui me correspond mieux : je vais essayer d’écrire un article en même temps que je bosse sur mon projet. Une sorte de journal de bord, en mode « devlog maison ». On verra bien ce que ça donne !
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Le besoin
&lt;/h2&gt;&lt;p&gt;J’auto-héberge quelques projets persos sur un Raspberry Pi, y compris ce blog d’ailleurs. Franchement, ça marche super bien, et ça me permet de m’éclater un peu avec la gestion de serveur, le déploiement, tout ça.
&lt;/p&gt;&lt;p&gt;Le seul vrai souci que j’ai rencontré, c’est cette histoire d’IP dynamique. Alors oui, avec nos box actuelles, les IP ont tendance à rester stables pas mal de temps… mais ce la n&#039;est pas garanti.
&lt;/p&gt;&lt;p&gt;Dernièrement, j’ai eu la « chance » d’avoir mon IP changée plusieurs fois en une seule semaine, alors qu&#039;elle était stable depuis des mois. Et devoir mettre à jour les enregistrements DNS à la main, c’est clairement pas fun. Surtout que pour connaître la nouvelle IP, faut être chez soi. Pratique, hein ?
&lt;/p&gt;&lt;p&gt;Ce qu’il me faudrait, c’est un petit script qui vérifie régulièrement si mon IP a changé, et qui met à jour mes DNS direct chez le registrar. Automatiser un peu tout ça, quoi.
&lt;/p&gt;&lt;p&gt;Par chance, mon registrar est OVH. Et même si pas mal de monde aime râler sur leurs offres ou certaines décisions techniques, personellement je trouve qu’ils font vraiment des efforts pour filer un coup de main aux devs.
&lt;/p&gt;&lt;p&gt;Petit flashback : en 2021, quand le data center de Strasbourg a pris feu, plein de sites hébergés chez OVH sont tombés en rade. Je vais pas relancer le débat sur les backups, c’est pas le sujet ici, mais forcément, tout le monde cherchait à remettre son site en ligne au plus vite. Sauf que l’interface web (le fameux manager) était complètement saturée.
&lt;/p&gt;&lt;p&gt;C’est là que je suis tombé sur un article de wikitwist.com qui parlait de cet événement... mais sous un angle un peu différent : celui de l’API d’OVH. Et franchement, elle est super bien conçue et très bien documentée. Elle permet, entre autres, de gérer ses enregistrements DNS. Du coup, je me suis dit : pourquoi ne pas en profiter pour automatiser un peu tout ça ?
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.wikitwist.com/panne-ovh-comment-utiliser-lapi-pour-changer-votre-zone-dns/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;l&#039;article de wikitwist sur l&#039;API d&#039;OVH
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Le plan
&lt;/h2&gt;&lt;p&gt;Mon FAI ne m’aide pas vraiment à récupérer facilement mon IP publique (en IPv4), du coup j’ai dû trouver une autre solution pour connaître mon adresse depuis l’extérieur. Je pourrais tout simplement interroger un service en ligne qui me retourne mon IP, y’en a plein. Mais bon... les solliciter en boucle, ça me gêne un peu, surtout quand on sait pas trop ce qu’ils font des infos qu’on leur envoie.
&lt;/p&gt;&lt;p&gt;Heureusement, j’ai déjà un serveur externe (VPS chez OVH), en dehors de mon réseau local. Et faire un petit script PHP pour qu’il affiche mon IP, franchement, c’est pas plus compliqué que quelques lignes. Du coup, j’ai décidé de créer cette première brique que j’ai appelée &quot;KIP&quot;, un petit jeu de mots entre “keep” et “IP”. J’aime bien, ça sonne comme l&#039;acronyme KISS.
&lt;/p&gt;&lt;p&gt;Ensuite, la seconde partie : un script qui va chercher cette IP, la compare avec celle qu’il a en mémoire, et si jamais elle a changé, il met à jour les DNS via l’API d’OVH. Et comme j’ai très envie de me mettre sérieusement à Go, je me suis dit que ce serait un projet parfait pour ça. Appelons ce futur script &quot;GoKeep&quot;, ça colle bien au concept.
&lt;/p&gt;&lt;p&gt;Pour être tout à fait transparent : j’avais déjà créé une première version de ces deux utilitaires en PHP avec Symfony. Mais avec un peu de recul, utiliser Symfony pour quelquechose d&#039;aussi simple, c&#039;est comme ouvrir un vortex par la porte des étoiles pour travailler son swing. Trop lourd, trop contraignant à maintenir. Donc là, on repart sur du plus léger, plus fun à coder, et qui colle mieux à mes envies du moment.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/DarkChyper/kip&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;KIP a &quot;simple&quot; API to get infos from your IP
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/DarkChyper/DDOManager&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;DDOManager is a &quot;small&quot; tool to deal with dynamic IP at home
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; KIP
&lt;/h2&gt;&lt;p&gt;Cette fois, je veux que la partie &quot;code&quot; reste aussi simple que possible. L’idée, c’est de renvoyer juste l’essentiel : la date et l’heure actuelles (au fuseau horaire de mon VPS), l’adresse IP, le port utilisé, et pourquoi pas le hostname pour faire joli. Le tout, bien proprement formaté en JSON. Et quand je dis &quot;récupérer&quot;, je parle bien du côté utilisateur : aucune donnée n’est stockée côté serveur (à part ce que les logs Apache enregistrent par défaut). Juste une réponse simple, directe, sans prise de tête.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-25&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-25&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;&amp;lt;?php
header(&amp;apos;Content-Type: application/json&amp;apos;);

date_default_timezone_set(&amp;apos;Europe/Paris&amp;apos;);

$ip = $_SERVER[&amp;apos;REMOTE_ADDR&amp;apos;];
$hostname = gethostbyaddr($ip);

$response = [
    &amp;apos;date&amp;apos; =&amp;gt; date(&amp;apos;Y-m-d&amp;apos;),
    &amp;apos;heure&amp;apos; =&amp;gt; date(&amp;apos;H:i:s&amp;apos;),
    &amp;apos;ip&amp;apos; =&amp;gt; $ip,
    &amp;apos;port&amp;apos; =&amp;gt; $_SERVER[&amp;apos;REMOTE_PORT&amp;apos;],
    &amp;apos;hostname&amp;apos; =&amp;gt; $hostname,
    &amp;apos;user_agent&amp;apos; =&amp;gt; $_SERVER[&amp;apos;HTTP_USER_AGENT&amp;apos;] ?? &amp;apos;Unknown&amp;apos;
];

echo json_encode($response, JSON_PRETTY_PRINT)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Je ne vais pas m’étendre ici sur la mise en ligne du script, car dans mon cas, c’est du très classique : j’ai un utilisateur dédié sur le serveur, le code est dans un dossier public_html à l’intérieur de son $HOME, et j’ai créé un VirtualHost Apache spécifique juste pour ce &quot;mini-site&quot;. Le tout passe sous HTTPS grâce à Certbot.
&lt;/p&gt;&lt;p&gt;Par contre, qui dit public dit potentiellement abusé. Et même si le script ne conserve rien, je préfère poser une petite limite de requêtes pour éviter qu’un bot ne vienne me ping 100 fois par seconde. Pour ça, rien de plus fiable et direct qu’iptables.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-26&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-26&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;sudo iptables -V
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Protégeons l&#039;accès SSH. Parce qu’on ne veut surtout pas se bloquer soi-même en appliquant des règles un peu trop strictes... Non, je ne parle pas d&#039;expérience, voyons 🙃
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-27&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-27&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ensuite on ajoute la limite des nouvelles connexions à 1/seconde/ip.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-28&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-28&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m hashlimit \
--hashlimit 1/sec --hashlimit-burst 5 --hashlimit-mode srcip \
--hashlimit-name http_limit -j ACCEPT

sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -m hashlimit \
--hashlimit 1/sec --hashlimit-burst 5 --hashlimit-mode srcip \
--hashlimit-name https_limit -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Enfin on rejette les excès (et rien d&#039;autre !!!)
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-29&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-29&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;sudo iptables -A INPUT -p tcp --dport 80 -j REJECT --reject-with tcp-reset
sudo iptables -A INPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On peut vérifier les règles avec la commande
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-30&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-30&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;sudo iptables -L -v --line-numbers
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     2519 1055K ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
2      102  6942 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh
3       19  1140 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:https ctstate NEW limit: up to 1/sec burst 5 mode srcip
4        3   160 REJECT     tcp  --  any    any     anywhere             anywhere             tcp dpt:http reject-with tcp-reset
5       24  1060 REJECT     tcp  --  any    any     anywhere             anywhere             tcp dpt:https reject-with tcp-reset

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
&lt;/pre&gt;&lt;p&gt;Il est important de vérifier que les pages web sont encore accessible à ce stade, sans couper la connexion SSH. Si ce n&#039;est pas le cas, il faut recommencer en supprimant toutes les règles :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-32&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-32&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;sudo iptables -F
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Si tout est bon, on installe le paquet pour les garder au redémarrage :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-33&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-33&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;apt install iptables-persistent
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;L’installeur demande si l&#039;on enregistre les règles actuelles pour IPv4 =&gt; Oui. Pour IPv6, chacun son choix (moi j’ai mis Non). Ensuite on vérifie l&#039;enregistrement comme ceci :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-34&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-34&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;cat /etc/iptables/rules.v4
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt; GOKeep
&lt;/h2&gt;&lt;p&gt;Ça fait des années que j’ai envie de me mettre à un autre langage orienté back-end, sans jamais réussir à trancher. Dans ma liste, il y avait Rust et Golang. Rust, tout le monde en parle comme du messie, même si la courbe d’apprentissage peut faire un peu peur, et toutes les vidéos que j&#039;ai pu voir parlaient de subtilités de gestion de mémoire... Pour un langage moderne (de bas niveau), on se retrouvait avec beaucoup de sujets qui rappellent l’époque du C. Du coup, j’ai opté pour Go. (mais je ne ferme pas la porte à Rust, juste je ne peux pas faire les deux en même temps...)
&lt;/p&gt;&lt;p&gt;Pour me faire une idée, j’ai regardé pas mal de vidéos sur le sujet, et deux d&#039;entre elles m&#039;ont aidé dans mon choix.
&lt;/p&gt;&lt;p&gt;La première, c’est celle de Grafikart : un comparatif entre Go et JavaScript, très accessible, avec des exemples concrets, sans trop s’attarder sur les limitations.
&lt;/p&gt;&lt;p&gt;La seconde, c’est la présentation de Jean-Laurent de Morlhon à DevoxxFR : “Pourquoi Maurice ne doit surtout pas coder en Go”. Là, on entre dans le dur : il liste pas mal de &quot;limitations&quot; du langage — formatage imposé du code, gestion très manuelle des erreurs, syntaxe plutôt verbeuse...
&lt;/p&gt;&lt;p&gt;Mais en fait, tous ces points qui sont censés être des défauts, je les ai trouvés... apaisants. Moins de choix, moins de réflexions inutiles... donc moins de charge mentale. Attention, cela ne veut pas dire qu’on ne peut pas être créatif avec Go. C’est un peu comme avec le protocole Gemini : ça paraît simpliste et limitant, mais au final, avoir un cadre rigide pousse à la créativité. Et c’est justement l’objectif de Go : coder plus vite, plus simplement, sans sacrifier la lisibilité ni la performance.
&lt;/p&gt;&lt;p&gt;Et si je devais donner un ultime argument : un code compilé en Go donne un unique binaire autonome, qui s&#039;exécute sans aucune dépendance. Même pas besoin d’avoir Go installé pour le lancer. Pour le DevOps, c’est juste royal.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=e8zL5PD8164&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Découverte du langage Go pour les développeurs JavaScript
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=LIFZPzupwgs&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Pourquoi Maurice ne doit surtout pas coder en GO
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je ne sais pas encore si ce choix s’avérera judicieux sur la durée, mais pour l’instant, il me convient parfaitement.
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Structure du script
&lt;/h3&gt;&lt;p&gt;La structure du projet est assez simple :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Récupération de l&#039;IP actuelle
&lt;/li&gt;&lt;li&gt;Récupération de l&#039;IP en mémoire
&lt;/li&gt;&lt;li&gt;Si les deux adresses ne sont pas concordantes, alors on récupère la liste des domaines et sous domaines à gérer
&lt;/li&gt;&lt;li&gt;Via l&#039;API d&#039;OVH on vient modifier l&#039;adresse IP des DNS de type A pour chaque sous domaines
&lt;/li&gt;&lt;li&gt;Enregistrement de la nouvelle IP
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Le tout avec des logs.
&lt;/p&gt;&lt;p&gt;J&#039;aurais également besoin de deux fichiers, le premier qui ne contiendra que l&#039;adresse IP &quot;en mémoire&quot;, .ip_history et un second qui contient les informations nécessaires à la gestion de l&#039;API d&#039;OVH, .godnsfile. Ces fichiers doivent être présents à la racine du dossier home de l&#039;utilisateur courant. Voici la structure du fichier .godnsfile :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-35&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;JSON&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-35&quot; class=&quot;overflow-auto&quot; alt=&quot;language JSON&quot; lang=&quot;json&quot;&gt;{
  &amp;quot;applicationKey&amp;quot;: &amp;quot;votre_app_key&amp;quot;,
  &amp;quot;applicationSecret&amp;quot;: &amp;quot;votre_app_secret&amp;quot;,
  &amp;quot;consumerKey&amp;quot;: &amp;quot;votre_consumer_key&amp;quot;,
  &amp;quot;domains&amp;quot;: [
    {
      &amp;quot;uri&amp;quot;: &amp;quot;example.com&amp;quot;,
      &amp;quot;subs&amp;quot;: [&amp;quot;www&amp;quot;, &amp;quot;api&amp;quot;, &amp;quot;blog&amp;quot;]
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt; Maintenant, on code
&lt;/h3&gt;&lt;p&gt;On est maintenant prêt à passer à la phase la plus satisfaisante du projet : écrire du code. J’écris finalement cette partie de l’article après avoir terminé le développement de la solution, parce que c’était plus simple pour moi de rester concentré sur la découverte du langage, de faire des allers-retours avec la documentation, et de tester plein de petites choses sans avoir à formuler tout ça proprement en même temps. Bref, j’ai préféré coder d’abord, écrire ensuite. (tout le monde ne sait pas coder et blogguer en même temps...)
&lt;/p&gt;&lt;p&gt;On commence par la base : interroger mon service KIP et récupérer mon IP publique.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-36&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-36&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;package main

import (
  &amp;quot;fmt&amp;quot;
  &amp;quot;io&amp;quot;
  &amp;quot;net/http&amp;quot;
)

func main() {
  resp, err := http.Get(&amp;quot;https://kip.lhoir.me&amp;quot;)
  if err != nil {
    fmt.Println(err)
    panic(err)
  }
  defer resp.Body.Close()

  body, err := io.ReadAll(resp.Body)
  if err != nil {
    fmt.Println(err)
    panic(err)
  }

  fmt.Println(string(body))
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Je lance avec `go run main.go` et... magie ! Mon JSON s’affiche dans le terminal. On a notre point de départ. C&#039;est vraiment agréable d&#039;avoir autant d&#039;outils déjà intégré au langage. Finalement, pour des scripts simples, la plus grande difficulté de Go (de ce que j&#039;en vois) est de connaître la bonne librairie de base pour réaliser l&#039;action que l&#039;on souhaite.
&lt;/p&gt;&lt;p&gt;Notons l’utilisation de defer : un mot-clé tout simple, mais super pratique. Il permet de différer la fermeture de la connexion HTTP à la fin de la fonction, sans risquer de l’oublier plus tard. Moins d’oublis, moins de bugs.
&lt;/p&gt;&lt;p&gt;Plutôt que de bricoler une extraction à coups de regex ou de split, Go propose de typer proprement une réponse JSON via une struct. Je pourrai me contenter de ne déclarer que le champ &quot;ip&quot;, mais autant faire les choses proprement.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-37&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-37&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;import (
  &amp;quot;encoding/json&amp;quot;
)

[...]

type ResponseData struct {
  Date      string `json:&amp;quot;date&amp;quot;`
  Time      string `json:&amp;quot;time&amp;quot;`
  IP        string `json:&amp;quot;ip&amp;quot;`
  Port      string `json:&amp;quot;port&amp;quot;`
  Hostname  string `json:&amp;quot;hostname&amp;quot;`
  UserAgent string `json:&amp;quot;user_agent&amp;quot;`
}

[...]

  var data ResponseData
  err = json.Unmarshal(body, &amp;amp;data)
  if err != nil {
    fmt.Println(err)
    panic(err)
  }

  currentIp := data.IP
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;C’est là qu’on commence à sentir un des aspects les plus décriés de Go : sa gestion des erreurs. Chaque appel potentiellement risqué est suivi d’un if err != nil { ... }. C’est clair, c’est explicite, mais... qu’est-ce que c’est répétitif. J’ai vite trouvé une astuce récurrente dans les vidéos de devs Go : créer une petite fonction utilitaire check() qui encapsule ce comportement, que je veux unique dans mon script : afficher l&#039;erreur et planter comme un lâche. Et hop, on remplace tous les &quot;if err != nil&quot; par de simples appels à &quot;check(err)&quot;. On réduit drastiquement le nombre de lignes de notre code.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-38&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-38&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;func check(e error) {
  if e != nil {
    log.Printf(&amp;quot;ERROR: %v&amp;quot;, e)
    log.Println(&amp;quot;=== End check ===&amp;quot;)
    panic(e)
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-39&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-39&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;import (
  &amp;quot;os&amp;quot;
)

[...]

  home, err := os.UserHomeDir()
  check(err) // c&amp;apos;est mieux non ?
  historyPath := home + &amp;quot;/.ip_history&amp;quot;

  previous, err := os.ReadFile(historyPath)
  check(err)

  if string(previous) != currentIp {
    fmt.Println(&amp;quot;Nouvelle IP :&amp;quot;, currentIp)
  } else {
    fmt.Println(&amp;quot;IP inchangée :&amp;quot;, currentIp)
  }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Go n’est pas un langage orienté objet dans le sens classique du terme, mais sa capacité à définir des structures de données typées, propres et claires est franchement plaisante.
&lt;/p&gt;&lt;p&gt;Certains parlent même de &quot;POO implicite&quot; en Go, grâce à l’usage de struct et de receiver functions.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://devopssec.fr/article/programmation-orientee-objet-golang&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;La programmation orientée objet dans le langage Go
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Bon, je ne vais pas réécrire tout le script ici. La suite consiste à utiliser la lib officielle d’OVH pour identifier les enregistrements DNS correspondants, les mettre à jour, et rafraîchir la zone.
&lt;/p&gt;&lt;p&gt;Une fois le script fonctionnel, j&#039;ai remplacé l&#039;affichage des erreurs par un système de log avec &quot;gopkg.in/natefinch/lumberjack.v2. Ce qui me permet d&#039;enchainer sur le système d&#039;import des dépendances.
&lt;/p&gt;&lt;p&gt;Un truc que j’ai vraiment apprécié en Go, c’est son système de gestion des dépendances. Contrairement à Composer (PHP) ou Maven (Java), ici pas de fichier de conf à remplir à la main, pas de commandes ésotériques pour initialiser un projet. Tu importes un package, tu fais un go run ou un go build, et Go télécharge tout ce qu’il faut.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-40&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;BASH&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-40&quot; class=&quot;overflow-auto&quot; alt=&quot;language BASH&quot; lang=&quot;bash&quot;&gt;go get github.com/ovh/go-ovh/ovh

# Go a automatiquement mis à jour le fichier go.mod et ajouté une entrée dans go.sum pour verrouiller la version.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et même pour du code local (dans le même projet), il est possible de structurer son application avec des packages maison. Il suffit de les placer dans des sous-dossiers, puis de les importer avec leur chemin relatif:
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-41&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;GO&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-41&quot; class=&quot;overflow-auto&quot; alt=&quot;language GO&quot; lang=&quot;go&quot;&gt;import &amp;quot;monprojet/utils&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pas besoin d’autoload, de configuration compliquée ni de réflexion sur l’arborescence du namespace. Autre point fort : Go impose de ne pas avoir de dépendances non utilisées, comme pour les variables. Si tu déclares un import que tu n’utilises pas... le compilateur t’envoie bouler. C’est brutal, mais ça force à garder un code propre. Un peu à la Unix : chaque outil fait une chose, mais il le fait bien.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Conclusion
&lt;/h2&gt;&lt;p&gt;J&#039;utilise le couple Kip et GoKeep depuis quelques semaines et j&#039;en suis ravi. Ce projet m’a permis de poser mes premières briques en Go, et franchement... j’ai adoré.
&lt;/p&gt;&lt;p&gt;C’est un langage qui respire la simplicité sans être simpliste. J’ai à peine effleuré ce qu’il propose : je n’ai pas encore joué avec les pointeurs, ni touché aux goroutines ou aux channels, qui sont pourtant parmi les concepts les plus puissants de Go. Mais rien que ce petit script m’a donné envie d’aller plus loin, de creuser davantage, et surtout de réécrire d&#039;autres outils que j’avais bricolés en PHP ou Bash avec ce nouveau langage. (Le moteur de ce blog ? Tempo ?)
&lt;/p&gt;&lt;p&gt;J’ai ensuite demandé à ChatGPT de me générer un joli README.md pour accompagner le projet. Oui j&#039;utilise les outis d&#039;IA (ou LLM) sans avoir honte... cela ferait un bon article de blog.
&lt;/p&gt;&lt;p&gt;Le code est maintenant disponible sur mon dépôt GitLab, pour ceux que ça intéresse, ou pour les curieux qui veulent voir un exemple simple et concret d’usage de l’API OVH en Go.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://gitlab.com/dark-open/kip&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;dépôt GIT du projet &quot;Kip&quot;
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://gitlab.com/dark-open/gokeep&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;dépôt GIT du projet &quot;GoKeep&quot;
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Et toi, quel est le projet, le besoin, qui t&#039;as motivé à apprendre un langage de programmation, voir le langage Golang ?&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-05-27-live-blog-coding-et-golang.html" />
    
    <published>2025-05-27T15:55:27Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-04-08-symfony-validator-pour-les-regles-fonctionnelles.html</id>
    <title type="html">Symfony/Validator pour les règles fonctionnelles
</title>
    <updated>2025-04-08T14:07:08Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Symfony/Validator pour les règles fonctionnelles
&lt;/h1&gt;
        &lt;img alt=&quot;Illustration représentant le paramétrage des règles dans Symfony, image générée par IA.&quot; src=&quot;https://darkblog.lhoir.me//assets/2025-04-08-symfony-validator/music_studio.png&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;blockquote&gt; Il est crucial de ne jamais se fier aux données provenant d&#039;un utilisateur.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;En tant que développeur web et en raison de la fréquence des interactions avec les formulaires et les API, la validation doit être une préoccupation constante dans nos développements. L&#039;un des avantages d&#039;un framework comme Symfony est la disponibilité d&#039;outils pratiques, tels que symfony/validator, qui facilitent la validation des données provenant de sources externes.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Validator de Symfony
&lt;/h2&gt;&lt;p&gt;La génèse du module Validator remonte à la version 2.1 de Symfony (2012), où l&#039;équipe de développement a décidé d&#039;intégrer une solution de validation basée sur des standards reconnus. La spécification JSR-303 Bean Validation a été choisie pour sa robustesse et sa flexibilité. L&#039;intégration de cette spécification dans Symfony a permis de créer un module de validation puissant et extensible, capable de répondre aux besoins variés des développeurs.
&lt;/p&gt;&lt;p&gt;Le module permet de centraliser les règles de validation, ce qui facilite la maintenance et la réutilisabilité du code, il offre également une grande flexibilité en permettant de créer des contraintes personnalisées et de les appliquer à différents niveaux de l&#039;application.
&lt;/p&gt;&lt;p&gt;L&#039;utilisation de ce module est particulièrement bien intégré au reste de l&#039;écosystème Symfony, comme les formulaires et Doctrine, ce qui permet de bénéficier d&#039;une cohérence de validation tout au long du cycle de vie des données.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/symfony/validator
&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;https://github.com/symfony/validator
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://symfony.com/doc/current/validation.html
&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;https://symfony.com/doc/current/validation.html
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://jcp.org/en/jsr/detail?id=303
&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;https://jcp.org/en/jsr/detail?id=303
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Un exemple de validation simple sur une entité :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-10&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-10&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;use Symfony\Component\Validator\Constraints as Assert;

class User
{
    #[Assert\NotBlank(message: &amp;quot;Le nom ne peut pas être vide.&amp;quot;)]
    #[Assert\Length(min: 3, max: 50, minMessage: &amp;quot;Le nom doit contenir au moins {{ limit }} caractères.&amp;quot;)]
    private string $name;
    [...]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Un second exemple avec une contrainte personnalisée, la vérification d&#039;un numéro de téléphone français. Nous avons besoins de 2 nouvelles classes :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-11&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-11&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;use Symfony\Component\Validator\Constraint;

#[\Attribute]
class FrenchPhoneNumber extends Constraint
{
    public string $message = &amp;quot;Le numéro de téléphone &amp;apos;{{ value }}&amp;apos; n&amp;apos;est pas un numéro français valide.&amp;quot;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-12&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-12&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class FrenchPhoneNumberValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || &amp;apos;&amp;apos; === $value) {
            return;
        }

        if (!preg_match(&amp;apos;/^(0[67]\d{8}|\+33[67]\d{8})$/&amp;apos;, $value)) {
            $this-&amp;gt;context-&amp;gt;buildViolation($constraint-&amp;gt;message)
                -&amp;gt;setParameter(&amp;apos;{{ value }}&amp;apos;, $value)
                -&amp;gt;addViolation();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Validation que l&#039;on peut ensuite utiliser sur une entité avec notre nouvel attribut.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-13&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-13&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;class User
{
[...]
    #[FrenchPhoneNumber]
    private string $phone;
[...]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dans Symfony, tout est un service. En partant de ce principe, il est possible d’injecter des dépendances directement dans une classe Validator pour effectuer des vérifications avancées via d’autres services ou repositories. Cependant, une fois le code écrit, la règle de validation restera fixe et s’appliquera de la même manière, quel que soit le contexte. Mais pourrait-on permettre aux utilisateurs de paramétrer eux-mêmes certaines contraintes tout en s’appuyant sur le Validator de Symfony ?
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; MusicBox
&lt;/h2&gt;&lt;p&gt;Imaginons MusicBox, une entreprise qui met à disposition des musiciens des salles de répétition, de mini-concert et d’enregistrement dans les grandes agglomérations. Ces espaces, situés à proximité de chez eux, offrent l’avantage d’être parfaitement insonorisés et équipés en fonction de l’abonnement choisi : micros, pianos, batteries, système de sonorisation ou d’enregistrement. Pour gérer son activité, MusicBox fournit à ses franchisés un logiciel en SaaS permettant d’administrer les salles, les abonnements, la facturation, les réservations et le matériel.
&lt;/p&gt;&lt;p&gt;Bien que rattaché à la marque, chaque franchisé doit gérer son activité en tenant compte des contraintes spécifiques à ses locaux, des réglementations d’urbanisme locales et des besoins de ses abonnés. En se focalisant sur la réservation des salles, trois grandes catégories de règles se dégagent : le contrôle des délais, l’interdiction des enchaînements, et les limites périodiques. L&#039;application de gestion doit intégrer ces règles tout en offrant aux gestionnaires la possibilité de les paramétrer finement afin d’adapter les conditions aux spécificités de chaque site.
&lt;/p&gt;&lt;p&gt;Pour résumer, l’objectif est de lier des validateurs personnalisés, définis en dur dans le code, à des configurations spécifiques enregistrées en base de données. Nous allons mettre en place toute la mécanique nécessaire pour permettre l’ajout de nouveaux paramétrages simplement en intégrant un nouveau validateur dans le code.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Maintenant, on code
&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-04-08-symfony-validator/validator_fonctionnel.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-04-08-symfony-validator/validator_fonctionnel.png&quot; alt=&quot;Diagramme qui résume ce que l&#039;on va céer
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je ne détaillerai pas la création d’un projet Symfony de base dans cet article. Je pars du principe que vous disposez déjà d’un projet fonctionnel avec une base de données et des entités. Tout le code présenté ici sera disponible dans un dépôt GitLab, accompagné d’une démo accessible pour tester les fonctionnalités.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://gitlab.com/DarkChyper/music_box
&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;https://gitlab.com/DarkChyper/music_box
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://musicbox.lhoir.me
&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;https://musicbox.lhoir.me
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Commençons par créer une interface et une classe abstraite qui serviront de base pour toutes les règles de validation des demandes de réservation de salle.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-14&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-14&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Control\Booking;

use App\Entity\BookingControl;
use Symfony\Component\Form\FormBuilderInterface;

interface BookingControlInterface
{
    public function getLabel(): string;
    public function setBookingControl(EntityControlInterface $bookingControl): ?ControlInterface;
    public function getBookingControl(): ?EntityControlInterface;
    public function getFormFields(FormBuilderInterface $form): FormBuilderInterface;
}
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-15&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-15&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Control\Booking;

use App\Entity\BookingControl;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraint;

abstract class BookingControlAbstract extends Constraint implements BookingControlInterface
{
    private EntityControlInterface $bookingControl;

    public function setBookingControl(EntityControlInterface $bookingControl): ?ControlInterface
    {
        $this-&amp;gt;bookingControl = $bookingControl;

        return $this;
    }

    public function getBookingControl(): ?EntityControlInterface
    {
        return $this-&amp;gt;bookingControl;
    }

    public function getFormFields(FormBuilderInterface $form): FormBuilderInterface
    {
        return $form;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Passer par l’abstraction pour la méthode getFormFields() permet de définir des champs communs à toutes les validations, sans nécessiter de données externes (repository ou services). Un autre avantage est de ne pas dépendre directement de l’interface, ce qui offre la possibilité d’avoir plusieurs abstractions définissant des formulaires différents.
&lt;/p&gt;&lt;p&gt;L’utilisation du patron Bridge permet ici de séparer l’abstraction (BookingControlAbstract) de son implémentation réelle (BookingControl). Ainsi, il devient possible de modifier l’une sans impacter l’autre, ce qui améliore la flexibilité et la maintenabilité du code.
&lt;/p&gt;&lt;blockquote&gt; Toutes les classes qui étendront cette abstraction étendront également Symfony\Component\Validator\Constraint.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Il est également nécessaire de créer une interface dont dépendra les entités en base :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-16&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-16&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Control;

interface EntityControlInterface
{
    public function getParameter(string $name): float|int|string|bool|null;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous avons désormais besoin d’une classe capable de recenser les contraintes à partir des classes présentes dans notre projet. Cette classe jouera un rôle clé dans les deux contextes suivants :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Côté administration : permettre la sélection d’une contrainte et la définition de ses paramètres spécifiques, qui seront ensuite enregistrés en base de données.
&lt;/li&gt;&lt;li&gt;Côté utilisateur : récupérer les contraintes configurées en base et les associer dynamiquement aux classes correspondantes dans le code. ceci se jouera au moment de la validation de la demande de réservation.
&lt;/li&gt;&lt;/ul&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-17&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-17&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Control\Booking;

use App\Entity\BookingControl;

class BookingControlCollection
{
    public const REGEX_VALIDATOR = &amp;apos;/^.*Validator$/&amp;apos;;
    private static array $bookingControls;

    public function __construct(iterable $bookingControls) {
        if (self::$bookingControls === null) {
            self::$bookingControls = [];

            /** @var BookingControlInterface $bookingControl */
            foreach ($bookingControls as $bookingControl) {
                $reflexion = new \ReflectionClass($bookingControl);
                if (!preg_match(self::REGEX_VALIDATOR, get_class($bookingControl))) {
                    self::$bookingControls[$reflexion-&amp;gt;getShortName()] = $bookingControl;
                }
            }
        }
    }

    public function getBookingControls(): array
    {
        return self::$bookingControls;
    }

    /**
     * @throws \Exception
     */
    public function getBookingControlByClassName(string $bookingControlClassName): BookingControlInterface
    {
        if (isset(self::$bookingControls[$bookingControlClassName])) {
            return clone self::$bookingControls[$bookingControlClassName];
        }

        throw new \Exception(&amp;apos;Unable to find service tagging &amp;quot;musicbox.booking_control&amp;quot; named &amp;apos;
            .$bookingControlClassName);
    }

    /**
     * @throws \Exception
     */
    public function getBookingControlByBookingControlEntity(BookingControl $bookingControl): BookingControlInterface
    {
        if (isset(self::$bookingControls[$bookingControl-&amp;gt;getControlClass()])) {
            return (clone self::$bookingControls[$bookingControl-&amp;gt;getControlClass()])-&amp;gt;setEventControl($bookingControl);
        }

        throw new \Exception(&amp;apos;Unable to find service tagging &amp;quot;musicbox.booking_control&amp;quot; named &amp;apos;
            .$bookingControl-&amp;gt;getControlClass());
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous tirons parti de l&#039;injection de dépendance de Symfony pour construire dynamiquement le tableau des contraintes disponibles, tout en utilisant le système de tags pour filtrer les éléments à injecter. Voici un exemple de configuration à ajouter dans le fichier config/service.yaml :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;YAMLservices:
    # ici on vient indiquer quelles classes sont tagguées,
    # on récupère les 2 classes par règle, d&amp;apos;où le tri par regex dans la classe de collection
    App\Validator\Constraints\BookingControls\:
        resource: &amp;apos;../src/Validator/Constraints/BookingControls/*&amp;apos;
        tags: [ musicbox.booking_control ]
    # il est possible de tagguer les fichiers un à un.
    # L&amp;apos;avantage est de ne pas devoir filtrer dans la classe BookingControlModelCollection

    # ici on indique que le 1er argument doit être une collection de classes tagguées
        App\Control\Booking\BookingControlCollection:
        arguments: [ !tagged musicbox.booking_control ]
&lt;/pre&gt;&lt;p&gt;Pour pouvoir enregistrer les contrôles configurés par les administrateurs, nous avons besoin d&#039;une entité qui implément l&#039;interface EntityControlInterface.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-19&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-19&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

class BookingControl implements EntityControlInterface
{
#[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $label = null;

    #[ORM\Column(length: 255)]
    private ?string $controlClass = null;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(nullable: false)]
    private ?Subscription $subscription = null;

    /**
     * @var array&amp;lt;string,int|string|bool|float&amp;gt;
     */
    #[ORM\Column(type: Types::JSON)]
    private array $parameters = [];

    [...]
    public function getParameter(string $name): float|int|string|bool|null
    {
        if (isset($this-&amp;gt;parameters[$name])) {
            return $this-&amp;gt;parameters[$name];
        }

        return null;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et voici un exemple de formulaire permettant d&#039;enregistrer les paramétrages spécifiques en se basant sur cette entité.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-20&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-20&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;class BookingControlType extends AbstractType
{
    public function __construct(
        private readonly BookingControlCollection $bookingControlCollection,
    ) {
    }

    /**
     * @throws \Exception
     */
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        /** @var BookingControl $bookingControl */
        $bookingControl = $builder-&amp;gt;getData();
        $control = $this-&amp;gt;bookingControlCollection-&amp;gt;getBookingControlByBookingControlEntity($bookingControl);
        $builder
            -&amp;gt;add(&amp;apos;label&amp;apos;, TextType::class, [
                &amp;apos;label&amp;apos; =&amp;gt; &amp;apos;form.common.label&amp;apos;,
                &amp;apos;data&amp;apos; =&amp;gt; $bookingControl-&amp;gt;getLabel(),
                &amp;apos;required&amp;apos; =&amp;gt; true,
            ])
            -&amp;gt;add(&amp;apos;subscription&amp;apos;, EntityType::class, [
                &amp;apos;label&amp;apos; =&amp;gt; &amp;apos;form.booking_control.label.subscription&amp;apos;,
                &amp;apos;class&amp;apos; =&amp;gt; &amp;apos;App\Entity\Subscription&amp;apos;,
                &amp;apos;choice_label&amp;apos; =&amp;gt; &amp;apos;label&amp;apos;,
                &amp;apos;choice_value&amp;apos; =&amp;gt; &amp;apos;id&amp;apos;,
                &amp;apos;multiple&amp;apos; =&amp;gt; false,
                &amp;apos;required&amp;apos; =&amp;gt; true,
            ])
            -&amp;gt;add(&amp;apos;parameters&amp;apos;, HiddenType::class, [
                &amp;apos;data&amp;apos; =&amp;gt; json_encode($options[&amp;apos;data&amp;apos;]-&amp;gt;getParameters()),
            ]);
        $builder
            -&amp;gt;get(&amp;apos;parameters&amp;apos;)
            -&amp;gt;addModelTransformer(new CallbackTransformer(
                function ($tagsAsArray): string {
                    // transform the array to a string
                    $jsonEncoded = json_encode($tagsAsArray);
                    if (false === $jsonEncoded) {
                        throw new \Exception(&amp;apos;Error encoding json&amp;apos;);
                    }

                    return $jsonEncoded;
                },
                function ($tagsAsString): array {
                    return json_decode($tagsAsString, true);
                }
            ))
        ;

        // ici on appel les champs spécifiques de chaque contrainte
        $builder = $control-&amp;gt;getFormFields($builder);

        $builder-&amp;gt;add(&amp;apos;save&amp;apos;, SubmitType::class, [
            &amp;apos;label&amp;apos; =&amp;gt; &amp;apos;form.common.save&amp;apos;,
        ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver-&amp;gt;setDefaults([
            &amp;apos;data_class&amp;apos; =&amp;gt; BookingControl::class,
        ]);
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Passons maintenant enfin à la création de nos contraintes. Par exemple la limite périodique.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-21&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-21&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Validator\Constraints\BookingControls;

[use ...]

class BookingControlLimitPeriodic extends BookingControlAbstract
{
    public const DEFAULT_HOURS = 1;
    public const LIMIT_PERIOD_WEEK = 0;
    public const LIMIT_PERIOD_MONTH = 1;
    public const FIELD_LIMIT_HOURS = &amp;apos;limitHours&amp;apos;;
    public const FIELD_LIMIT_PERIOD = &amp;apos;limitPeriod&amp;apos;;

    public function getLabel(): string
    {
        return &amp;apos;constraint.control_periodic.label&amp;apos;;
    }

    public function getFormFields(FormBuilderInterface $form): FormBuilderInterface
    {
        $control = $this-&amp;gt;getControl();
        $form
            -&amp;gt;add(&amp;apos;limitHours&amp;apos;, IntegerType::class, [
                &amp;apos;label&amp;apos; =&amp;gt; &amp;apos;Nombre d\&amp;apos;heures de réservation&amp;apos;,
                &amp;apos;required&amp;apos; =&amp;gt; true,
                &amp;apos;data&amp;apos; =&amp;gt; $control-&amp;gt;getParameter(&amp;apos;limitHours&amp;apos;) ?? self::DEFAULT_HOURS,
                &amp;apos;empty_data&amp;apos; =&amp;gt; self::DEFAULT_HOURS,
                &amp;apos;mapped&amp;apos; =&amp;gt; false,
                &amp;apos;constraints&amp;apos; =&amp;gt; [
                    // a little meta-constraint moment :)
                    new GreaterThan([&amp;apos;value&amp;apos; =&amp;gt; 0]),
                ],
            ])
            -&amp;gt;add(self::FIELD_LIMIT_PERIOD, ChoiceType::class, [
                &amp;apos;label&amp;apos; =&amp;gt; &amp;apos;Période&amp;apos;,
                &amp;apos;required&amp;apos; =&amp;gt; true,
                &amp;apos;data&amp;apos; =&amp;gt; $control-&amp;gt;getParameter(&amp;apos;limitPeriod&amp;apos;) ?? self::LIMIT_PERIOD_WEEK,
                &amp;apos;empty_data&amp;apos; =&amp;gt; self::LIMIT_PERIOD_WEEK,
                &amp;apos;mapped&amp;apos; =&amp;gt; false,
                &amp;apos;choices&amp;apos; =&amp;gt; [
                    &amp;apos;Hebdomadaire&amp;apos; =&amp;gt; self::LIMIT_PERIOD_WEEK,
                    &amp;apos;Mensuelle&amp;apos; =&amp;gt; self::LIMIT_PERIOD_MONTH,
                ],
            ]);

        $form-&amp;gt;addEventListener(FormEvents::PRE_SUBMIT, function ($event) {
            $data = $event-&amp;gt;getData();
            $parameters = [
                &amp;apos;limitHours&amp;apos; =&amp;gt; $data[&amp;apos;limitHours&amp;apos;],
                &amp;apos;limitPeriod&amp;apos; =&amp;gt; $data[&amp;apos;limitPeriod&amp;apos;],
            ];
            $data[&amp;apos;parameters&amp;apos;] = json_encode($parameters);

            $event-&amp;gt;setData($data);
        });

        return $form;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-22&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-22&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Validator\Constraints\BookingControls;

class BookingControlLimitPeriodicValidator extends ConstraintValidator
{
    [attributs]

    public function __construct(
            private readonly BookingRepository $bookingRepository,
        ) {
        }

        /**
         * @throws \DateMalformedStringException
         */
        public function validate(mixed $value, Constraint $constraint): void
        {
            if (!$constraint instanceof BookingControlAbstract) {
                return;
            }

            /* @var Booking $booking */
            $this-&amp;gt;booking = $value;

            /** @var BookingControl $bookingControl */
            $bookingControl = $constraint-&amp;gt;getControl();

            $this-&amp;gt;hoursLimit = intval($bookingControl-&amp;gt;getParameter(BookingControlLimitPeriodic::FIELD_LIMIT_HOURS));
            $period = intval($bookingControl-&amp;gt;getParameter(BookingControlLimitPeriodic::FIELD_LIMIT_PERIOD));

            match ($period) {
                BookingControlLimitPeriodic::LIMIT_PERIOD_WEEK =&amp;gt; $this-&amp;gt;validateByWeek(),
                BookingControlLimitPeriodic::LIMIT_PERIOD_MONTH =&amp;gt; $this-&amp;gt;validateByMonth(),
                default =&amp;gt; throw new \LogicException(&amp;apos;La période de limitation est inconnue&amp;apos;),
            };

            $this-&amp;gt;validator();
        }
        [la suite du code dans le repository]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;BookingControlLimitPeriodic contient la logique côté administration, notamment le libellé et les champs spécifiques à enregistrer. Elle hérite de notre abstraction BookingControlAbstract, elle-même basée sur la classe Constraint de Symfony.
&lt;/p&gt;&lt;p&gt;La classe BookingControlLimitPeriodicValidator prend en charge la validation des données saisies dans le formulaire de réservation. Elle encapsule les règles métier à appliquer ainsi que les messages de retour destinés à l&#039;utilisateur en cas d&#039;erreur.
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Comment déclencher la validation ?
&lt;/h3&gt;&lt;p&gt;Il existe plusieurs manières de déclencher la validation des réservations.
&lt;/p&gt;&lt;p&gt;Une première approche consiste à créer une méthode validateBooking() dans un service dédié, appelée lors du traitement de la demande de réservation. Cette méthode pourrait récupérer dynamiquement la liste des contraintes depuis la base de données, puis faire appel au système de validation de Symfony pour les appliquer.
&lt;/p&gt;&lt;p&gt;Une autre approche, celle que j’ai choisie dans mon exemple, consiste à créer une contrainte principale (BookingConstraint) de type CLASS_CONSTRAINT, appliquée directement sur l’entité de réservation. Dans ce cas, la méthode validate() de cette contrainte est responsable de charger dynamiquement les contraintes à appliquer, et de générer les messages d&#039;erreur le cas échéant.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-23&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-23&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

#[\Attribute]
class BookingConstraint extends Constraint
{
    public function validatedBy(): string
    {
        return get_class($this).&amp;apos;Validator&amp;apos;;
    }

    public function getTargets(): string
    {
        return self::CLASS_CONSTRAINT;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-24&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-24&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;namespace App\Entity;

use App\Repository\BookingRepository;
use App\Validator\Constraints as AppAssert;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Table(name: &amp;apos;musicbox_booking&amp;apos;)]
#[ORM\Entity(repositoryClass: BookingRepository::class)]
#[AppAssert\BookingConstraint]
class Booking
{
[...]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;J’apprécie particulièrement cette méthode pour sa centralisation et son intégration directe dans le cycle de validation. Toutefois, elle présente une limite importante : il devient difficile de contourner la validation, par exemple dans des cas spécifiques où l’on souhaiterait enregistrer des réservations sans appliquer les contraintes métier.
&lt;/p&gt;&lt;p&gt;Un cas concret en dehors de l&#039;exemple de Music Box serait l’import de réservations depuis un système tiers, où les règles métier auraient déjà été validées en amont. Dans ce scénario, il peut être nécessaire d’enregistrer les données sans répéter la validation.
&lt;/p&gt;&lt;p&gt;Pour répondre à ce besoin, une solution hybride est envisageable : ne pas appliquer la contrainte principale sur l’entité directement, mais la déclencher manuellement via un service de réservation dédié. Cela permet de garder le contrôle sur les cas où la validation doit être effectuée ou non.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Pour aller plus loin
&lt;/h2&gt;&lt;p&gt;Maintenant que tout le système est en place, l’ajout de nouvelles contraintes devient extrêmement simple : il suffit de créer deux classes dans le dossier des contraintes, et Symfony les détectera automatiquement. La nouvelle contrainte sera ainsi immédiatement disponible sans configuration supplémentaire.
&lt;/p&gt;&lt;p&gt;Actuellement, notre entité BookingControl est liée aux abonnements, mais on pourrait facilement étendre le système pour lier un contrôle à une salle spécifique, ou à tout autre élément du domaine.
&lt;/p&gt;&lt;p&gt;Il serait également possible d’introduire une gestion fine des droits utilisateurs. Par exemple, chaque contrainte pourrait définir les rôles ou privilèges nécessaires pour pouvoir être contournée. Ainsi, si un utilisateur tente de déposer une réservation qui dépasse son quota, celle-ci serait bloquée. En revanche, si un administrateur effectue la même réservation pour ce compte, il pourrait passer outre la contrainte grâce à ses droits élevés.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;J’espère que cette plongée dans l’architecture des contrôles dynamiques vous aura donné des idées, que ce soit pour structurer vos propres règles métier ou pour mieux tirer parti de la puissance de Symfony.
&lt;/p&gt;&lt;p&gt;N’hésitez pas à partager vos retours, vos questions ou même vos propres variantes de ce type de système. Dites moi également si ce genre d&#039;article assez dense vous intéresse.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Codez bien !&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-04-08-symfony-validator-pour-les-regles-fonctionnelles.html" />
    
    <published>2025-04-08T10:58:37Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-03-25-algorithmie-plages-horaires.html</id>
    <title type="html">Algorithmie : le chevauchement de plages horaires
</title>
    <updated>2026-02-02T14:09:59Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Algorithmie : le chevauchement de plages horaires
&lt;/h1&gt;
        &lt;p&gt;L&#039;engagement à produire des articles mieux structurés et plus documentés présente un défi : ils demandent beaucoup plus de temps à rédiger. Cela est d&#039;autant plus vrai lorsqu&#039;on souhaite illustrer des concepts techniques avec un code propre et fonctionnel, surtout si l&#039;on est un peu trop perfectionniste.
&lt;/p&gt;&lt;p&gt;En attendant voic un petit article rapide, un minuscule extrait du code qui arrive prochainement.
&lt;/p&gt;&lt;p&gt;Comment vérifier simplement que deux plages horaires ne se chevauchent pas ? Vous ne vous êtes peut-être jamais posé la question, pourtant ce problème est omniprésent : réservation de salles, gestion du temps, etc.
&lt;/p&gt;&lt;p&gt;Imaginons une première plage horaire allant de A à B, et une seconde de C à D. En écartant les cas où A et C sont égaux, ainsi que ceux où B et D le sont également, il reste six possibilités. Comme on dit, une image vaut mieux que mille mots. Voici un schéma illustrant ces six possibilités :
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-03-25/plages_horaires.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-03-25/plages_horaires.png&quot; alt=&quot;Un schema representant 6 couples de plages horaires, 4 se chevauchent, les deux dernier ne se chevauchent pas.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Avec ce schéma on peut se rendre compte que deux plages horaires se chevauchent si ces deux conditions sont strictements vraies :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;C est inférieur à B
&lt;/li&gt;&lt;li&gt;D est supérieur à A
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Ce qui donnerait en code PHP :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-9&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-9&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;&amp;lt;?php
class TimeRange {
    private $start;
    private $end;

    public function __construct($start, $end) {
        $this-&amp;gt;start = $start;
        $this-&amp;gt;end = $end;
    }

    public function overlapsWith(TimeRange $other) {
        return $this-&amp;gt;start &amp;lt; $other-&amp;gt;end &amp;amp;&amp;amp; $this-&amp;gt;end &amp;gt; $other-&amp;gt;start;
    }
}

// Example usage:
$range1 = new TimeRange(10, 20);
$range2 = new TimeRange(15, 25);

if ($range1-&amp;gt;overlapsWith($range2)) {
    echo &amp;quot;The time ranges overlap.&amp;quot;;
} else {
    echo &amp;quot;The time ranges do not overlap.&amp;quot;;
}
?&amp;gt;
``&lt;/code&gt;&lt;/pre&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-03-25-algorithmie-plages-horaires.html" />
    
    <published>2025-03-25T17:01:52Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-01-13-une-minute-par-semaine.html</id>
    <title type="html">Une minute par semaine
</title>
    <updated>2026-02-02T14:09:59Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Une minute par semaine
&lt;/h1&gt;
        &lt;p&gt;En 2025, je relance le projet &quot;une minute par semaine&quot;. Chaque semaine, je publie une vidéo d&#039;une minute qui illustre ce qui se passe dans ma vie, ce que je peux voir, ou vivre au quotidien.
&lt;/p&gt;&lt;p&gt;Comme évoqué dans le titre, c&#039;est la cinquième fois que je (re)lance ce projet, projet que j&#039;ai plusieurs fois abandonné donc, par lassitude ou par changement de fonctionnement des réseaux sur lesquels je publiais (non je ne veux pas faire de story, juste publier des post avec une vidéo...).
&lt;/p&gt;&lt;p&gt;Voici les contraintes que je m&#039;impose pour cet exercice :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Je ne filme qu&#039;avec mon smartphone, pas avec celui d&#039;un proche. Par contre, je peux être sur la vidéo si quelqu&#039;un me filme avec mon appareil.
&lt;/li&gt;&lt;li&gt;Autant que possible, des plans fixes, pas d&#039;ajout d&#039;éclairage, de modification de ce qui se passe.
&lt;/li&gt;&lt;li&gt;Le montage se fait sur le smartphone, sans transition entre les plans, sans ajout de texte, de son ou de musique et sans modifier la piste son d&#039;origine.
&lt;/li&gt;&lt;li&gt;Je me garde le droit de cacher des visages, surtout des enfants.
&lt;/li&gt;&lt;li&gt;Je filme du lundi au dimanche pour une sortie le lundi suivant.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;L&#039;idée est de créer des capsules vidéo de souvenirs à voir et à revoir dans le temps, sans forcément pouvoir tout faire entrer dans cette minute. J&#039;y mets ce que j&#039;ai envie, rien sur demande, et cette liberté avec cadre est assez plaisante.
&lt;/p&gt;&lt;p&gt;Un peu agacé par le changement permanent du fonctionnement des réseaux sociaux, je vais maintenant publier ces vidéos sur PeerTube, j&#039;ai trouvé le service de mensnumeriques.fr qui propose un espace de 50 Go gratuitement. Je fais une sauvegarde sur un drive privé, sur un disque dur en local et aussi peut être un ultime backup sur YouTube, peut être le seul réseau que je trouve acceptable, modulo un stop pub :)
&lt;/p&gt;&lt;p&gt;Chaque semaine, je mettrai à jour cet article avec les nouveaux liens, afin de ne pas polluer le blog avec un grand nombre d&#039;articles peu fournis.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Saison 2025
&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/vr1ivnoieZaCmUrLWuxGwf&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202552 Du lundi 29 décembre 2025 au dimanche 04 janvier 2026
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/u58yZ7gCxBhNuCf8tE7uNt&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202551 Du lundi 22 au dimanche 28 décembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/t9tmsddBqW5wLFcDQMoGi4&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202550 Du lundi 15 au dimanche 21 décembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/o6V3gnZ4oALs27bRmE5mW2&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202549 Du lundi 08 au dimanche 14 décembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/e444M8dPP1qXDpVvwhstCS&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202548 Du lundi 01 au dimanche 07 décembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/36s8HzwBRcUP3qKByg4yT8&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202547 Du lundi 24 au dimanche 30 novembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/7EjZoeZqiJQvvjusa9xDKX&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202546 Du lundi 17 au dimanche 23 novembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/frapm1QU4ZwmmcmvgFjZrs&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202545 Du lundi 10 au dimanche 16 novembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/nWXBBVPpSCWWPXFXDdvaQ3&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202544 Du lundi 03 au dimanche 09 novembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/d9phgWjJ6c6HqpwdGHjHz&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202543 Du lundi 27 octobre au dimanche 02 novembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/uDCJk9o6HuRPvpvnkokgwG&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202542 Du lundi 20 au dimanche 26 octobre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/7BjrbkxZXxyxrjJXFCFemb&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202541 Du lundi 13 au dimanche 19 octobre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/sWTkKxZW61ZWzBFbb3SXje&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202540 Du lundi 06 au dimanche 12 octobre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/pnyxYvazQxzHJ233FQSTDd&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202539 Du lundi 29 septembre au dimanche 05 octobre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/iMaMcXyVuYYJazwMai2LaB&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202538 Du lundi 22 au dimanche 28 septembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/t9MV5gcPag2U7wG11AaRdV&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202537 Du lundi 15 au dimanche 21 septembre 2025 
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/rLmsuVaaBSkLQUHcU7T7RE&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202536 Du lundi 08 au dimanche 14 septembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/7QMwozWXZq5dS4wiQRz15W&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202535 Du lundi 01 au dimanche 07 septembre 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/oo7kCcM7EM8EKRQZSXY5Rv&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202534 Du lundi 25 au dimanche 31 août 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/aKymswbimxcPoeweiuvEjX&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202533 Du lundi 18 au dimanche 24 août 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/6WVmPNqEUt95bS2wuW697f&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202532 Du lundi 11 au dimanche 17 août 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/sXuFovVxbYLkx8KCZdVvpm&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202531 Du lundi 04 au dimanche 10 août 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/iS13RmYq16bu1hwMCjTFAr&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202530 Du lundi 28 juillet au dimanche 03 août 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/dsr9DMhfdR6Gkz4JBEZjs1&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202529 Du lundi 21 au dimanche 27 juillet 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/1bcrom7SjZQ3UPmidNLtsh&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202528 Du lundi 14 au dimanche 20 juillet 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/6Fq3ngpd4BiAhCxXu8yhPq&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202527 Du lundi 7 au dimanche 13 juillet 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/qdQZUh34QFzecdrWd6MMv4&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202526 Du lundi 30 juin au dimanche 06 juin 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/mnmNphsiA3F9jSopAMpSW8&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202525 Du lundi 23 au dimanche 29 juin 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/6UtVY6g5tHJaYUDS9QDJvf&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202524 Du lundi 16 au dimanche 22 juin 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/mghiuogaxBWaqMQWwo2SkK&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202523 Du lundi 09 au dimanche 15 juin 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/weKUghpQqUWfdCamrbLpUJ&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202522 Du lundi 02 au 08 juin 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/cH7FgiaXtpAv1WPmxKUVCv&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202521 Du lundi 26 mai au dimanche 01 juin 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/jewzwJAsMoURWHbMuSXZNT&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202520 Du lundi 19 au dimanche 25 mai 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/11isSqKbcT8mjnUc5aC2qm&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202519 Du lundi 12 au dimanche 18 mai 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/tgsvHbqgfrMSuz14uy7i9C&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202518 Du lundi 05 au dimanche 11 mai 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/a6WfDpaXEWTcsgD64yphxY&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202517 Du lundi 28 avril au dimanche 04 mai 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/5M5GJcFJBEaJzQBtwNnLTr&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202516 Du lundi 21 au dimanche 27 avril 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/6Sjf9C4oocJNJ7y4zFfo5b&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202515 Du lundi 14 au dimanche 20 avril 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/ha5L78WT6cZ25wUtidkhB9&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202514 Du lundi 07 au dimanche 13 avril 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/vkkKLvnui8KEKTpAscbwNw&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202513 Du lundi 31 mars au dimanche 06 avril 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/hymE2r2KYmXh39ybbfBMfo&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202512 Du lundi 24 au dimanche 30 mars 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/ubD6VXb6CSye4ZeEUqMb9w&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202511 Du lundi 17 au dimanche 23 mars 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/qu1SaQVHoaMUnyGedzs92m&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202510 Du lundi 10 au dimanche 16 mars 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/cMCXMmq366wvAtzrhi4kDD&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202509 Du lundi 03 au dimanche 09 mars 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/hmpTiSefTw4rqfnpk4UkXF&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202508 Du lundi 24 février au dimanche 02 mars 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/5DdzZ498fjM8PFDo9tyTyP&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202507 Du lundi 17 au dimanche 23 février 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/3F5fEKihYixcwQj6x1BZKR&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202506 Du lundi 10 au dimanche 16 février 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/3s3ks9yzwgu8dfBE5AyUB5&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202505 Du lundi 03 au dimanche 09 février 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/tnwgHDQQLAzuhavJ5z3AfV&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202504 Du lundi 27 janvier au dimanche 02 février 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/xkLe8ZW8sXyjojGYDsCXz3&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202503 Du lundi 20 au dimanche 26 janvier 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/7U65c9v2smPBCtzFeAdFYe&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202502 Du lundi 13 au dimanche 19 janvier 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://peertube.mesnumeriques.fr/w/kVQaSgvqDNFbKKCt62oThC&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;#202501 Du lundi 6 au dimanche 12 janvier 2025
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Bon visionnage !&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-01-13-une-minute-par-semaine.html" />
    
    <published>2025-01-13T16:51:53Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2025-01-07-projets-et-objectifs-2025.html</id>
    <title type="html">Projets et objectifs personnels de 2025
</title>
    <updated>2026-02-02T14:09:59Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Projets et objectifs personnels de 2025
&lt;/h1&gt;
        &lt;p&gt;Avant toute chose, meilleurs vœux à tous ceux qui lisent ces lignes, peu importe le moment. Qui dit nouvelle année, dit &quot;bonnes résolutions&quot; de début d&#039;année. Vous savez ces résolutions qui partent d&#039;un bon sentiment, d&#039;une envie de renouveau ou d&#039;amélioration de notre quotidien et qui s&#039;oublient aussitôt que survient la galette des rois.
&lt;/p&gt;&lt;p&gt;Alors comme je n&#039;ai pas envie de tomber dans ce cliché, et de devoir me trouver des excuses en fin d&#039;année pour ces nouveaux échecs, je vais tenter une approche plus réaliste.
&lt;/p&gt;&lt;p&gt;Je vais mettre par écrit ces &quot;objectifs et projets personnels&quot;, en mettre le plus possible pour qu&#039;il y en ait au moins deux ou trois qui aboutissent.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; La remise en forme
&lt;/h2&gt;&lt;p&gt;Grand classique des bonnes résolution de début d&#039;année, mais aussi d&#039;arrivée des beaux jours ou de la rentrée, je veux perdre du poids.
&lt;/p&gt;&lt;p&gt;Mon objectif : passer sous la barre des 100 kg au 31/12/2025.
&lt;/p&gt;&lt;p&gt;Il s&#039;agit d&#039;un processus que j&#039;ai déjà initié, il y a plus d&#039;un an, sans limite de temps. Je ne dirai pas que c&#039;est un échec, vu que j&#039;ai perdu 1 kg, mais que cela n&#039;a pas fonctionné (ou n&#039;est pas très efficace.) vue que cette perte est sur 12 mois. Néanmoins, je vois que j&#039;ai plus régulièrement eu une activité physique, que j&#039;arrive un peu mieux à l&#039;intégrer à mon rythme.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Moins de passivité, plus d&#039;action
&lt;/h2&gt;&lt;p&gt;J&#039;imagine que je dois pouvoir trouver mes statistiques de temps passé sur YouTube, Insta et autres sources de contenus pas souvent de qualité qui me maintiennent passif, mais sans les avoir, je sais que ce temps est infiniment trop long.
&lt;/p&gt;&lt;p&gt;Dans cette case, je regroupe plusieurs objectifs.
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Publier au moins 12 articles &quot;intéressants&quot; cette année. Je précise &quot;intéressants &quot;, car j&#039;ai plein d&#039;idées de brèves ou d&#039;articles comme celui que vous lisez, mais j&#039;aimerai aussi du contenu un peu plus travaillé, avec plus de recherches et mieux sourcés.
&lt;/li&gt;&lt;li&gt;Arriver en version 1.0 du projet Tempo
&lt;/li&gt;&lt;li&gt;Commencer les différents projets que j&#039;ai en tête comme &quot;411&quot;, &quot;Semainier&quot; et RSS to e-book, j&#039;explique ces projets un peu après.
&lt;/li&gt;&lt;li&gt;Suivre enfin ces cours sur fusion 360 que j&#039;ai acheté chez Abrège académie, voir transférer ce savoir vers Blender.
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://www.abregeacademy.com/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;le site de Abrège Académy pour devenir un &quot;maker autonome&quot;
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Tempo 1.0
&lt;/h3&gt;&lt;p&gt;J&#039;ai eu pas mal de retours sur ce projet, par des amis, mais aussi par la communauté sur le fediverse. Il y a pas mal de concurrence sur ce domaine, mais comme je suis le premier utilisateur de ce projet et qu&#039;il n&#039;a aucun but commercial, je continue de le faire évoluer.
&lt;/p&gt;&lt;p&gt;Suite à un toot de Ploum, j&#039;ai bien envie de créer un ultime moyen de partage de l&#039;information, la newsletter. L&#039;enjeu sera de le faire de la manière la moins invasive dans la vie privée des gens et en gérant avec la plus grande prudence leur adresse email.
&lt;/p&gt;&lt;p&gt;J&#039;aimerais également corriger tous les petits bugs que j&#039;ai déjà repérés, les fautes de frappe dans les textes, avoir une section avec les tarifs au fil des années... et on devrait arriver à la version 1.0 :)
&lt;/p&gt;&lt;p&gt;Dans un futur plus lointain, pour la v2.0, j&#039;aimerais que ce site ne propose que des pages statiques, et que le back-end génère les mises à jour des pages en fonction des nouvelles informations. Pouvoir héberger le site sur un service tout petit, et avoir la BDD &quot;hors ligne&quot;.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://mamot.fr/@ploum/113639309455578336&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;le toot de Ploum
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Semainier (ou Weekly)
&lt;/h3&gt;&lt;p&gt;J&#039;avais commencé à travailler sur ce projet suite à une formation VueJS au boulot, voici le lien pour en savoir plus.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2024-04-26-projet-weekly-cadrage.html
&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;https://darkblog.lhoir.me/2024-04-26-projet-weekly-cadrage.html
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; 411
&lt;/h3&gt;&lt;p&gt;Une idée de projet de SAAS, un peu dans le même esprit que cet article.
&lt;/p&gt;&lt;p&gt;Le pitch : Se donner 4 objectifs à réaliser chaque jour pendant 1 an (ou un mois, ce n&#039;est pas encore complètement défini). L&#039;idée est que l&#039;on ne peut pas toujours être au top, on craque, et ça démotive de continuer des efforts. Par contre quand on a 4 objectifs quotidien, même malade, même démotivé, il y a en a peut-être au moins 1 que l&#039;on peut réaliser.
&lt;/p&gt;&lt;p&gt;Chaque jour, on vient indiquer les objectifs réussis, 4, c&#039;est un &quot;Kudos&quot;, 3 valent une médaille d&#039;or, 2 une médaille d&#039;argent, 1 le bronze, et si on ne fait aucun des objectifs, c&#039;est un &quot;oups&quot;, on reste positif, &quot;shit happens&quot;.
&lt;/p&gt;&lt;p&gt;Je serai le premier utilisateur de ce genre d&#039;outil, mes 4 objectifs depuis plus d&#039;un an sont : ne pas boire de soda, boire au moins 1l d&#039;eau, au moins 1 fruit consommé, une activité physique d&#039;au moins 10 minutes. Mais, pour d&#039;autre, cela pourrait être :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;ne pas fumer
&lt;/li&gt;&lt;li&gt;lire au moins un chapitre de livre
&lt;/li&gt;&lt;li&gt;ne pas laisser traîner mon linge sale
&lt;/li&gt;&lt;li&gt;au moins un repas sans viande
&lt;/li&gt;&lt;li&gt;une journée sans râler
&lt;/li&gt;&lt;li&gt;prendre plus de temps pour ses enfants
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Je vois bien des défis entre amis sur le nombre de kudos par mois, voir des challenges par type d&#039;objectifs, plusieurs personnes qui veulent arrêter de fumer peuvent se motiver ...
&lt;/p&gt;&lt;p&gt;J&#039;avais commencé à remplir un tableur pour suivre mes objectifs, on va dire que c&#039;est un début de PoC.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2025-01-07-projets-et-objectifs-2025/411.png&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2025-01-07-projets-et-objectifs-2025/411.png&quot; alt=&quot;Affichage d&#039;un tableaur, chaque ligne est un jour différent, il y a aussi 4 colonnes d&#039;objectifs avec des cases à cocher pour dire si c&#039;est réalisé ou non. et une autre case à droite avec le résultat de la journée : kudos, médaille d&#039;or, d&#039;argent de bronze ou oups.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; RSS to e-book
&lt;/h3&gt;&lt;p&gt;Une autre idée de projet SAAS, qui va avec l&#039;objectif de la section suivante, moins d&#039;écran, plus de livres.
&lt;/p&gt;&lt;p&gt;Je n&#039;arrive pas à lire mes flux RSS sur le PC. Je passe un temps fou sur mon smartphone pour des bêtises, alors y passer plus de temps pour des articles longs...
&lt;/p&gt;&lt;p&gt;J&#039;aimerai un outil qui me permette d&#039;agréger les contenus de mes flux RSS dans un e-book, chaque semaine, et que cela me l&#039;envoi sur ma Kindle. Un peu comme si j&#039;étais abonné à une revue, mais dont je choisirais les contenus.
&lt;/p&gt;&lt;p&gt;Je ne migrerai peut-être pas tous les flux sur cet outil, par exemple tempo l&#039;info n&#039;est valable que 24 h, mais pour le blog de Ploum, de Flozz ou de Zythom, ce serait un outil intéressant.
&lt;/p&gt;&lt;br /&gt;&lt;h3&gt; Des commentaires dans ce blog
&lt;/h3&gt;&lt;p&gt;Je réfléchis à un système de commentaires dans le blog qui soit compatible Gemini et HTML, qui ne nécessite pas de base de données. Ça se baserait sur l&#039;email. 
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Moins d&#039;écran, plus de livres
&lt;/h2&gt;&lt;p&gt;Je suis réaliste, je ne lirai pas un livre par jour ou par semaine, et encore moins de la grande littérature, alors je me donne l&#039;objectif de lire ces 3 livres :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Coder proprement de Robert C. Martin, livre que j&#039;ai commencé au moins 3 fois vu que je m&#039;y remets tous les 6 mois
&lt;/li&gt;&lt;li&gt;Plongée au cœur des Patrons de conception du site &quot;refactoring guru&quot;
&lt;/li&gt;&lt;li&gt;En route vers Symfony 6 de Fabien Potencier afin d&#039;avoir une vraie base solide du framework que j&#039;aime le plus utiliser
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Alors les deux derniers étant sur liseuse, je triche un peu pour le moins d&#039;écran, mais ce sont 3 livres qui m&#039;aideront aussi professionnellement, une motivation supplémentaire
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://refactoring.guru/fr/design-patterns
&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;https://refactoring.guru/fr/design-patterns
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; les reste, en vrac
&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;monter en compétences sur la CI-CD pour intégrer ça à mes pipeline de projets personnels
&lt;/li&gt;&lt;li&gt;Avoir une chaîne Hi-fi pour le bureau, pour me passer du casque sur les oreilles toute la journée, misant sur un casque à conduction osseuse et un micro sur table pour communiquer avec mes collègues et donc la musique sur la chaîne. J&#039;aimerais réaliser cela sous forme de projet avec un raspberry pi, un DAC, un lecteur de cd externe USB, les HP de mon ancienne vraie chaîne Hi-fi...
&lt;/li&gt;&lt;li&gt;créer un écran e-ink pour l&#039;affichage de la domotique + Tempo à la maison
&lt;/li&gt;&lt;li&gt;Me mettre sur Home Assistant (ce qui rejoint l&#039;écran précédant)
&lt;/li&gt;&lt;li&gt;vider le garage pour en faire, à terme, un bureau pour le télétravails
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Je mettrai à jour ce billet à chaque fois qu&#039;un des objectifs sera atteint ou qu&#039;un des projets aura bien avancé.
&lt;/p&gt;&lt;br /&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2025-01-07-projets-et-objectifs-2025.html" />
    
    <published>2025-01-07T12:58:33Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2024-11-18-reverse-skyjo.html</id>
    <title type="html">Le reverse au Skyjo
</title>
    <updated>2026-02-02T14:09:59Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Le reverse au Skyjo
&lt;/h1&gt;
        &lt;img alt=&quot;Ma première partie de Skyjo, j&#039;ai gagné!&quot; src=&quot;https://darkblog.lhoir.me//assets/2024-11-18-reverse-skyjo/ma-premiere-partie.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Cet été, j&#039;ai participé pour la seconde fois au séminaire de mon entreprise, séminaire qui rassemble tous les salariés au même endroit pour 3 jours où l&#039;on &quot;profite à fond&quot; après avoir &quot;bossé à fond&quot; le reste de l&#039;année&quot;, dixit notre PDG.
&lt;/p&gt;&lt;p&gt;Durant ces 3 jours, j&#039;ai des super collègues qui m&#039;ont initié à un jeu de société créé en 2015 par Alexander Bernhardt en Allemagne et qui s&#039;appelle Skyjo.
&lt;/p&gt;&lt;p&gt;Pour rappel, au Skyjo, on a 4 colonnes de 3 lignes de cartes devant soi, face cachée. Le but du jeu est de cumuler le moins de point possible par partie, il est alors nécessaire de se débarrasser de ses grosses cartes pour d&#039;autres à valeur plus faible (voir négative !!).
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2024-11-18-reverse-skyjo/ma-premiere-partie.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2024-11-18-reverse-skyjo/ma-premiere-partie.jpg&quot; alt=&quot;Ma première partie de Skyjo, j&#039;ai gagné!
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Quelques semaines plus tard, avec mon épouse, nous avons reçu un couple d&#039;amis pour une soirée jeux, autant dire que j&#039;ai initié tout ce petit monde au Skyjo. Et après une série de 10 parties, nous avons imaginé des règles alternatives pour la suite de la partie :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;on tourne dans le sens antihoraire (le reverse du Uno)
&lt;/li&gt;&lt;li&gt;le but de chaque partie est de faire le plus de points
&lt;/li&gt;&lt;li&gt;on retranche les points à la fin de chaque partie au total déjà acquis
&lt;/li&gt;&lt;li&gt;le gagnant est celui qui a le moins de point à son total à la fin de la soirée
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2024-11-18-reverse-skyjo/une-partie-endiablee.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2024-11-18-reverse-skyjo/une-partie-endiablee.jpg&quot; alt=&quot;Une partie endiablée
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;C&#039;était vraiment intéressant de faire dévier les règles de cette façon, je me demande ce que l&#039;on peut imaginer sur d&#039;autres jeux.
&lt;/p&gt;&lt;p&gt;Et vous, vous revisitez les jeux de sociétés ?
&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2024-11-18-reverse-skyjo.html" />
    
    <published>2024-11-18T16:50:52Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2024-09-11-teletravail-bilan-1an.html</id>
    <title type="html">Bilan de 1 an de télétravail
</title>
    <updated>2026-02-02T14:09:59Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Bilan de 1 an de télétravail
&lt;/h1&gt;
        &lt;img alt=&quot;Un havre de paix à moins de 5 minutes de chez moi, en pleine ville !&quot; src=&quot;https://darkblog.lhoir.me//assets/2024-09-11-teletravail-bilan-1an/cover.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Début septembre, c&#039;est la rentrée (scolaire) et qui dit rentrée dit petit bilan de l&#039;année écoulée, l&#039;occasion idéale pour faire le point sur 1 an en total télétravail.
&lt;/p&gt;&lt;p&gt;En vrai, cela fait 3 mois que je repousse le moment d&#039;écrire cet article, par [manque de temps, manque d&#039;axe d&#039;écriture, peur de la page noire (dark thème oblige)],
&lt;/p&gt;&lt;p&gt;entourez mentalement l&#039;excuse qui vous conviendra le mieux.
&lt;/p&gt;&lt;p&gt;Reste qu&#039;à force de lire des ultra défenseurs du total télétravail raconter leur propagande et d&#039;entendre des avis, tout aussi tranchés, de personnes ne supportant pas l&#039;idée de ramener le travaille chez elles, j&#039;ai bien envie d&#039;apporter mon retour d&#039;expérience, en essayant d&#039;être le plus honnête possible, à défaut d&#039;être totalement objectif.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Mon retour d&#039;expérience
&lt;/h2&gt;&lt;p&gt;Commençons par les points réellement positifs. Aucun transport pour se rendre au bureau, c&#039;est incroyable. Les lundis ne sont plus une source de souffrance, les mauvaises nuits de l&#039;enfant ne sont plus aussi problématiques. Mais surtout, le fait de pouvoir amener mon fils à l&#039;école, régulièrement à pied, tous les matins, cela n&#039;a pas de prix.
&lt;/p&gt;&lt;p&gt;Les trajets du matin étaient une grande source de stress pour moi, les bouchons, le manque de place pour se garer... Je n&#039;arrivais jamais dans de bonnes conditions au bureau. Les retours n&#039;étaient pas mieux, pour peu que la journée ne se soit pas bien passée ou que je mette 3 fois le temps normal de trajet, je pestais dans la voiture. Ne me parlez pas du train, le rythme de 3 jours de grèves tous les 5 jours de la SNCF a achevé ma motivation envers ce mode de transport pour le travail.
&lt;/p&gt;&lt;p&gt;Bref, le temps de trajet n&#039;était pas un sas de décompression entre le boulot et la maison.
&lt;/p&gt;&lt;p&gt;Je fais plus souvent des pauses dans mon boulot, chose que je ne faisais absolument pas en présentiel. Et ces pauses sont doublement utiles, cela me permet de m&#039;aérer l&#039;esprit, quitter un peu l&#039;écran, comme toutes les pauses quoi, mais j&#039;en profite également pour avancer dans les corvées de la maison. Cuisine, ménage, petits bricolages, et la hantise des patrons anti-télétravail, des lessives ! 
&lt;/p&gt;&lt;p&gt;Oui, je lance ou pends des lessives en télétravail ! Mais je peux rassurer tous ces patrons, depuis l&#039;arrivée de l&#039;invention de Jacob Christian Schäffer, à savoir la machine à laver ou lave-linge en 1765 puis à l&#039;électrification de celle-ci en 1910 et sa démocratisation dans les foyers français depuis 1960, je ne suis plus obligé d&#039;aller au bord de la rivière pour laver le linge et cette corvée ne me prends plus des heures.
&lt;/p&gt;&lt;p&gt;Ouf !
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/Lave-linge&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Article wikipedia du lave-linge
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Et grâce à ces pauses plus régulières et beaucoup plus utiles au quotidien, j&#039;ai l&#039;esprit plus serein pour travailler et la déconnexion se fait dès que j&#039;éteins l&#039;ordinateur. 
&lt;/p&gt;&lt;blockquote&gt; En tout cas, pour moi, ca marche.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Cela ne se voit ni sur la balance ni sur mon physique, mais j&#039;ai plus de temps pour le sport également. Le défaut, c&#039;est de faire ses séances seul tout le temps, ce qui nuit à la régularité. J&#039;ai bien l&#039;application de suivi Strava qui permet de recevoir des encouragements régulièrement, mais cela n&#039;aide pas tout le temps.
&lt;/p&gt;&lt;p&gt;L&#039;autre facteur de cette non-perceptibilité de reprise du sport, c&#039;est le grignotage. Avoir accès à mes placards, c&#039;est le mal, la moindre frustration peut être accompagnée d&#039;un petit &quot;remontant&quot;. C&#039;est un point que je dois améliorer.
&lt;/p&gt;&lt;p&gt;Je ne pense pas que de travailler à distance soit synonyme de se couper des relations sociales. Ok, j&#039;avais déjà eu 2 collègues avec qui je discutais beaucoup, je les ai d&#039;ailleurs invitées au vin d&#039;honneur de notre mariage. Ces deux personnes sont quand même pour moi de l&#039;ordre de l&#039;exception lorsque je travaillais en total présentiel. Je n&#039;allais ni aux pauses clopes, ni aux pauses thé/café, et petit à petit, j&#039;ai fuis les &quot;vendredi petit déj&quot;, beaucoup trop riches. Du coup, c&#039;est assez difficile de discuter &quot;en off&quot; avec ses collègues. 
&lt;/p&gt;&lt;p&gt;Aujourd&#039;hui, à distance, on discute chaque matin au daily, au retour de pause du midi, ou entre temps quand il nous arrive un truc drôle ou non. On discute des émissions de la veille, des déménagements de chacun, de la rentrée, des vacances, des bricolages en cours, des potins de l&#039;entreprise... 
&lt;/p&gt;&lt;p&gt;Pour les points négatifs, c&#039;est vrai que les petits restos de temps en temps le midi, avec les collègues, ça manque un peu. Pareil pour les séances de sports à plusieurs. Je pense que si certains collègues, ou même les locaux, étaient proches géographiquement, j&#039;y passerai une fois dans le mois. Non pas parce qu&#039;il me manque des interactions humaines, mais juste pour casser la routine. C&#039;est là que je ne suis pas d&#039;accord avec les &quot;ultras du télétravail&quot;, oui une offre de total télétravail avec 1 jour de présentiel par mois/trimestre, c&#039;est du total télétravail, et non ce n&#039;est pas une énorme contrainte. Cela favoriserait le retour des populations dans des zones rurales autour des entreprises qui font le pari du total télétravail, tout en évitant de mettre toute la France en concurrence, voir une concurrence mondiale.
&lt;/p&gt;&lt;p&gt;Un autre point négatif, c&#039;est de travailler avec le casque tout le temps sur les oreilles... 
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2023-06-09-changement-de-cadre.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;il s&#039;agissait d&#039;un des points positifs lors de mon lancement dans cette aventure
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Ma chaîne hi-fi se faisant âgée, le tiroir du lecteur CD ne se ferme plus, les sortie HP grésillent/coupent, du coup, j&#039;écoute la musique au casque et je ne pense donc pas à le retirer de temps en temps pour reposer les oreilles et les cervicales. 
&lt;/p&gt;&lt;p&gt;Je cherche à la faire réparer, mais il n&#039;y a plus beaucoup de spécialistes et il faut payer cash 60 € pour qu&#039;on te dise si c&#039;est réparable ou non.
&lt;/p&gt;&lt;p&gt;Du coup, je cherche soit une remplaçante, soit la même pour récupérer des pièces. 
&lt;/p&gt;&lt;p&gt;Une autre solution serait de passer au micro déporté avec bouton pour l&#039;activer/desactiver, et un casque à conduction osseuse, plus léger, et qui laisse les oreilles libres. Et en même temps, le casque fournit par l&#039;entreprise est vraiment très bien conçu pour le télétravail (et le gaming), j&#039;en reparle dans la seconde partie de l&#039;article.
&lt;/p&gt;&lt;p&gt;Dernier point compliqué qui est vraiment propre à mon caractère : je ne m&#039;arrête plus. J&#039;ai toujours eu du mal à faire de vraies pauses, c&#039;est-à-dire avec rien à faire ou réaliser des activités juste pour le plaisir, sans objectif. &quot;Je dois faire mes séances de sport&quot;, &quot;je dois avancer sur la préparation des repas&quot;... Je n&#039;arrivais déjà pas à le faire en présentiel car, c&#039;est difficile de s&#039;isoler des autres, mais le souci s&#039;est exacerbé depuis que je suis à la maison. J&#039;y travaille.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Comment réussir le total télétravail ?
&lt;/h2&gt;&lt;p&gt;Je vais enfoncer des portes ouvertes, mais l&#039;aménagement du lieu de télétravail et l&#039;équipement de travail sont primordiaux.
&lt;/p&gt;&lt;p&gt;Peu importe le bureau, ce qui compte, c&#039;est de la lumière naturelle qui arrive directement dans la pièce, et un éclairage suffisant le restant du temps. Ne travaillez pas dans la pénombre. Idéalement, la pièce n&#039;est réservée qu&#039;au télétravail avec une porte qui ferme. Cela permet de travailler à des horaires où les autres membres de la maison dorment ou font beaucoup de bruit.
&lt;/p&gt;&lt;blockquote&gt;Je suis un mauvais élève sur ce point, car je suis sur le palier de l&#039;étage, mais je cherche des solutions. 
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Une très bonne chaise est un indispensable, on oublie celles de la cuisine ou les premiers prix, vous y passerait 8 heures par jour. Le top serait d&#039;avoir un bon soutient des lombaires, et un repose-pied au sol. Certains ne jurent que par les balles d&#039;assise, moi, je préfère alterner entre position confortable assis et position debout.
&lt;/p&gt;&lt;p&gt;Prochainement, je pense investir dans un tapis de marche, histoire de ne pas rester statique lorsque je suis debout. Cela rentabilise les réunions et permet d&#039;accéder aux 10.000 pas par jour même en cas de mauvais temps.
&lt;/p&gt;&lt;p&gt;Vous n&#039;aurez certainement pas la main sur le choix de l&#039;ordinateur. Par contre rien ne vous empêche d&#039;investir dans un grand écran, sur un bras articulé pour gagner de la place. Pareil pour le clavier et la souris, vous en aurez sans doute par l&#039;entreprise, mais il existe des périphériques avec une excellente ergonomie, vos muscles et tendons vous diront merci.
&lt;/p&gt;&lt;blockquote&gt;Si vous avez le choix du système d&#039;exploitation, passez sous Linux.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Pour le micro casque, c&#039;est difficile de donner un modèle en particulier, les gammes changent souvent. J&#039;ai un Arctis 9 de chez Steelseries que je trouve parfait pour le télétravail. Voici les points que trouve indispensable et que vous pouvez retrouver sur d&#039;autres modèles :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;il s&#039;agit d&#039;un casque fermé, qui englobe l&#039;oreille ce qui est très confortable
&lt;/li&gt;&lt;li&gt;il n&#039;a pas d&#039;atténuation du bruit active, ça consomme moins de batterie
&lt;/li&gt;&lt;li&gt;il est sans fil, mais radio, il est donc connecté à un périphérique propriétaire-USB (petit moins) mais profite d&#039;une grande portée, je me balade dans toute la maison sans soucis.
&lt;/li&gt;&lt;li&gt;il possède 2 canaux stéréos, avec une molette pour le volume général et une autre pour le mix entre les deux canaux. J&#039;utilise le premier pour l&#039;application de chat de l&#039;entreprise et le second canal pour la musique. 
&lt;/li&gt;&lt;li&gt;il y a un bouton pour ouvrir/fermer le micro et celui-ci à une LED d&#039;indication quand il est fermé
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Reste qu&#039;il s&#039;agit d&#039;un gros casque, il fait son poids, donc à vous de voir quels compromis vous voulez faire.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2024-09-11-teletravail-bilan-1an/casque.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2024-09-11-teletravail-bilan-1an/casque.jpg&quot; alt=&quot;Le casque Arctis 9 de chez Steelseries
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Pensez également à la décoration de la pièce, une déco professionnelle mais avec des touches personnelles, c&#039;est toujours plus agréable.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Entreprises, comment réussir le total télétravail ?
&lt;/h2&gt;&lt;p&gt;Je ne peux pas me mettre à la place de l&#039;entreprise, mais je peux indiquer ce qui aide l&#039;employé à bien travailler dans une entreprise en total télétravail.
&lt;/p&gt;&lt;p&gt;Premièrement, c&#039;est la confiance totale accordée par défaut. Ok, le processus d&#039;entretien dans mon entreprise actuelle a été plutôt rude et ne fonctionnera pas du tout avec des juniors. Plusieurs échanges avec différents interlocuteurs, dont un recruteur externe, des tests de niveau, des prises de références, échange technique en visio avec ma fuiture équipe... si on enlève la prise de référence, on ouvre le processus aux juniors et tout le monde est content.
&lt;/p&gt;&lt;p&gt;Ce n&#039;est pas facile, mais cela permet de rassurer l&#039;employeur, qui accorde alors plus facilement une confiance totale. La période d&#039;essai sert ensuite de dernier &quot;test&quot; grandeur nature, pour les deux parties.
&lt;/p&gt;&lt;p&gt;Une très grande transparence et accessibilité quant au fonctionnement de l&#039;entreprise, et cela dès le processus d&#039;entretien.
&lt;/p&gt;&lt;p&gt;Par exemple que toutes les équipes, dont les RH, aient un espace de partage de documents, un drive publique. Evidemment, il y a toujours des documents que l&#039;on ne souhaite pas partager entre équipes, soit parce qu&#039;ils sont en cours d&#039;élaboration, soit parce qu&#039;il s&#039;agit de données brutes. Je n&#039;ai pas besoin de voir tous les documents comptables, mais avoir accès à des bilans, aux CODIR, COPIL etc. cela devient très intéressant. Dans ce cas, il s&#039;uffit d&#039;avoir un drive privé, en plus du publique, par équipe et gérer un peu les droits. Le but ici est d&#039;éviter l&#039;isolement de l&#039;employé, que la vie de l&#039;entreprise lui échappe totalement. Si on crée des documents publiques (entre les services) et que l&#039;on communique dessus, c&#039;est parfait.
&lt;/p&gt;&lt;p&gt;La communication est donc très importante. En plus des drives et des mails, proposer des outils de travail collaboratif est indispensable, à commencer par l&#039;échange en audio. Réaliser les cérémonies agiles en visio, c&#039;est très bien, mais pour les échanges de tous les jours, l&#039;audio est largement suffisant s&#039;il est bien pensé. Un canal par équipe, des canaux de réunions virtuelles, des canaux de concentration pour rester visible mais plus tranquille, seront une base solide d&#039;échange.
&lt;/p&gt;&lt;blockquote&gt; On utilise TeamSpeak au bureau.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Enfin avoir des points réguliers avec les différentes équipes, et surtout, son responsable direct me semble obligatoire, si possible des points prévus dans les processus de l&#039;entreprise, et pas uniquement à la demande du salarié.
&lt;/p&gt;&lt;p&gt;Cela pourrait sembler contre intuitif, mais pour réussir à garder le moral et l&#039;énergie de tous en total télétravail, il faut se voir au moins une fois par an en présentiel. Que ce soit un séminaire, se retrouver ou organiser un meet-up, donner la possibilité à une équipe de se rendre à un salon ou une convention, le but est de se voir en vrai et de sortir du cadre quotidien.
&lt;/p&gt;&lt;p&gt;Je ne dis pas qu&#039;il est impossible de garder la motivation sans jamais se voir, mais un séminaire de 3 jours dans un lieu qui nous fait sortir du cadre du travail, c&#039;est fortement appréciable. En plus, les économies d&#039;échelle de ne pas avoir de bâtiment sont un peu redistribuées de cette façon aux employés, ce qui motive à travailler à fond toute l&#039;année pour profiter à fond du séminaire.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Pour finir
&lt;/h2&gt;&lt;p&gt;Je suis totalement conquis par le total télétravail, un retour en total présentiel ne se ferait sans doute qu&#039;en changeant totalement de spécialité ou de métier, mais serait vraiment difficile. Un mode hybride est intéressant, mais il existe un réel gap quand on passe en total télétravail, qui ne convient pas à tout le monde.
&lt;/p&gt;&lt;p&gt;Reste à améliorer mes différents points négatifs afin de profiter encore plus de ce qui n&#039;est, finalement, qu&#039;une disposition de travail comme une autre.&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2024-09-11-teletravail-bilan-1an.html" />
    
    <published>2024-09-11T13:17:13Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2024-05-07-histoire-de-cintres.html</id>
    <title type="html">Une histoire de cintres
</title>
    <updated>2024-05-07T15:24:26Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Une histoire de cintres
&lt;/h1&gt;
        &lt;img alt=&quot;Photo de l&#039;atrocité d&#039;un entremêlement de cintres de formes et couleurs diverses&quot; src=&quot;https://darkblog.lhoir.me//assets/2024-05-07-histoire-de-cintres/cintres-non-ranges.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Petit billet de blog rapide un peu en mode &quot;3615 my life&quot; avec un début d&#039;intrigue à base de cintres.
&lt;/p&gt;&lt;p&gt;Oui des cintres, pour accrocher les vêtements dans des penderies, cette invention du diable que l&#039;on ne sait jamais vraiment où ranger entre deux lessives, qui traîne donc un peu à divers endroits de la maison, qui s&#039;emmêlent les uns aux autres...
&lt;/p&gt;&lt;p&gt;Je ne vais pas faire un tuto sur comment les ranger, des solutions simples existent comme un simple seau dans lequel on vient les mettre à la vertical, ou une barre de penderie dans une hauteur perdue de placard justement. Si l&#039;on est organisé, on peut également les laisser dans la penderie d&#039;où on a pris le vêtement et ne les récupérer que lorsque l&#039;on en a besoin...
&lt;/p&gt;&lt;p&gt;Personnellement, je préfère le rangement dans un espace perdu (ou plus ou moins perdu), je prends mon vêtement avec le cintre que je range à l&#039;endroit où j&#039;en aurai besoin pour faire sécher le linge la fois suivante.
&lt;/p&gt;&lt;p&gt;J&#039;ai donc besoin d&#039;une barre de penderie et des attaches. Évidemment, les chutes de barre que j&#039;ai dans le garage sont trop courtes... Mais j&#039;ai la chance d&#039;avoir un magasin de bricolage à 2 km à pied dans ma ville alors je profite de la pause du midi pour me dégourdir les jambes.
&lt;/p&gt;&lt;p&gt;Sur place, je trouve la barre dont j&#039;ai besoin, mais il y a une rupture totale de stock sur les fixations murales, et comme on est sur l&#039;heure du midi, pas un vendeur à l&#039;horizon.
&lt;/p&gt;&lt;p&gt;Bon, après sur ce genre de barre, il n&#039;y aura pas beaucoup de force mécanique sur les attaches, et comme les cintres seront &quot;vides&quot;, le poids ne sera pas colossal, c&#039;est donc un projet parfait pour l&#039;impression 3D. Mais je suis encore fébrile sur la conception 3D et je n&#039;ai pas le temps en ce moment. Je regarde rapidement sur Thingiverse, et il y a bien une personne qui partage des modèles compatibles avec la barre en magasin, parfait.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.thingiverse.com/thing:5838720&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Les fichiers STL de support de barre par I_K_B
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Petite impression de 3 heures; oui ma ender 3 pro est lente et un peu fatiguée; je peux passer au bricolage et enfin installer cette barre à cintres.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2024-05-07-histoire-de-cintres/porte-barre.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2024-05-07-histoire-de-cintres/porte-barre.jpg&quot; alt=&quot;L&#039;une des pièces imprimées et la barre qui tient les cintres :)
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Ça y est, je pense que j&#039;intègre enfin l&#039;impression 3D comme un outil à part entière, au même titre qu&#039;une ponceuse ou une défonceuse. Je vais arrêter de me poser la question de la légitimité de cette machine dans l&#039;atelier voir passer à un modèle plus performant et qui prendra plus de types de filaments.
&lt;/p&gt;&lt;p&gt;Et vous l&#039;impression 3D, gadget ou outil dans votre atelier ?&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2024-05-07-histoire-de-cintres.html" />
    
    <published>2024-05-07T15:24:26Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2024-04-26-projet-weekly-cadrage.html</id>
    <title type="html">Projet Weekly : présentation et cadrage
</title>
    <updated>2026-02-02T14:09:59Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Projet Weekly : présentation et cadrage
&lt;/h1&gt;
        &lt;img alt=&quot;Des exemples de semainiers étalés sur une table&quot; src=&quot;https://darkblog.lhoir.me//assets/2024-04-26-projet-weekly-cadrage/cover.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Il y a quelques jours, j&#039;ai eu la chance de suivre une formation sur VueJS dans le cadre de mon emploi. Quatre jours intensifs que j&#039;aimerais rapidement mettre à profit afin de ne pas trop oublier la quantité d&#039;informations que j&#039;ai ingurgité. Même si je vais en avoir besoin dans le cadre de mon travail, il risque de se passer plusieurs semaines avant que je ne puisse refaire du front-end.
&lt;/p&gt;&lt;p&gt;Cela tombe bien, j&#039;ai toujours une idée de projet personnel à réaliser qui n&#039;attendait qu&#039;un prétexte pour que je le développe.
&lt;/p&gt;&lt;p&gt;Mais je me connais assez pour savoir que si je pars directement sur le code, le projet ne verra jamais le jour, comprendre ici : ne sera jamais en production et je ne l&#039;utiliserai jamais.
&lt;/p&gt;&lt;p&gt;En même temps, rédiger tout un tas de documents qui finiront à la poubelle, j&#039;ai vraiment la flemme. Damned.
&lt;/p&gt;&lt;p&gt;En plus, qui dit nouvelle technologie veut également dire nouvelles façons d&#039;initialiser la structure de fichier du projet, lancer un nombre incroyable de commandes... Ça serait pas mal de capitaliser là-dessus.
&lt;/p&gt;&lt;p&gt;Et je ne sais pas si vous l&#039;avez remarqué, mais c&#039;est assez simple de trouver du contenu qui t&#039;explique comment démarrer un projet, la documentation pour développer est souvent bien fourni, par contre quand il faut commencer à mettre en production, il n&#039;y a plus personne. Pouvoir demander un coup de main, et de nouveau capitaliser dessus ne serait pas de trop.
&lt;/p&gt;&lt;p&gt;Bon si je résume, je ne me jette pas sur le code, mais je commence par cadrer le besoin et les fonctionnalités, et j&#039;avance pas à pas. Un peu comme ces développeurs &quot;super star&quot; qui codent en public sur Twitch avec un chat qui propose des solutions quand ils bloquent.
&lt;/p&gt;&lt;p&gt;Sauf que je n&#039;ai pas une grande audience, que je n&#039;aime pas trop coder en direct (syndrome de l&#039;imposteur). Par contre le pas-à-pas, cela me parle, c&#039;est ça de grandir avec des jeux en tour par tour.
&lt;/p&gt;&lt;p&gt;C&#039;est en faisant ce constat que je me suis rappelé que j&#039;essaye de tenir un blog. Et que rien ne m&#039;empêche d&#039;écrire une suite d&#039;articles qui ont pour but de faire avancer le projet, tout en partageant les ressources que j&#039;aurai chiné sur le web.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Weekly, un semainier tout bête
&lt;/h2&gt;&lt;p&gt;Le projet, c&#039;est simplement de créer un semainier. Voilà.
&lt;/p&gt;&lt;p&gt;À la base, un semainier, c&#039;est juste un bout de papier avec les jours de la semaine, et les repas que l&#039;on veut préparer pour les midis et soirs. On a toujours fait comme cela avec mon épouse, c&#039;est pratique pour faire la liste de courses et ne pas oublier de cuisiner un repas.
&lt;/p&gt;&lt;p&gt;Notre modèle a évolué en quelques années, passant de la simple liste de plats à un modèle élaboré avec la météo, quand on y pense, le mode de garde de notre fils, les sorties...
&lt;/p&gt;&lt;p&gt;Comme on en avait assez de refaire une grille toutes les semaines, on a créé un modèle vierge, que l&#039;on peut imprimer pour le remplir à la main. Parfois, on remplit tout sur un tableur avant de l&#039;imprimer.
&lt;/p&gt;&lt;p&gt;Ça marche bien.
&lt;/p&gt;&lt;p&gt;Et si le projet n&#039;aboutit pas ou si le projet tombe en panne, on pourra toujours revenir à nos papiers, donc je suis serein.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Cadrage du projet
&lt;/h2&gt;&lt;p&gt;Commençons par lister les règles métiers et les fonctionnalités que j&#039;aimerais retrouver.
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Affichage du semainier sur 10 jours en commençant le vendredi (jour des courses)
&lt;/li&gt;&lt;li&gt;Chaque journée est représentée sur une ligne horizontale, en 3 cases
&lt;/li&gt;&lt;li&gt;La première case contient les informations du jour, la date, le mode de garde de notre enfant et en bonus la météo
&lt;/li&gt;&lt;li&gt;La seconde et la troisième case affichent les repas du midi et du soir respectivement
&lt;/li&gt;&lt;li&gt;La météo [bonus] affichera les températures min et max de la journée et une icône pour résumer le temps de la journée (pluie, soleil...)
&lt;/li&gt;&lt;li&gt;Les appels à l&#039;API météo se fera côté backend
&lt;/li&gt;&lt;li&gt;La page d&#039;affichage sert également de page de modification, soit en activant un mode édition, soit à la volée.
&lt;/li&gt;&lt;li&gt;On doit pouvoir créer une nouvelle semaine. Les vendredis, samedis et dimanche en commun conservent leurs données.
&lt;/li&gt;&lt;li&gt;On doit pouvoir visualiser tout l&#039;historique des semaines
&lt;/li&gt;&lt;li&gt;Le tout ne doit être accessible que si l&#039;on est authentifié, donc une page d&#039;authentification
&lt;/li&gt;&lt;li&gt;Toutes les personnes identifiées auront un droit de lecture et d&#039;écriture.
&lt;/li&gt;&lt;li&gt;Les comptes utilisateurs seront en dur, pas d&#039;inscription possible
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Certaines fonctionnalités restent volontairement vagues, je ne sais pas encore comment je veux les implémenter.
&lt;/p&gt;&lt;p&gt;Je fais des choix très personnels dans ce besoin, le but n&#039;est pas de créer une application pour tous les besoins de tout le monde.
&lt;/p&gt;&lt;p&gt;Si la base du projet vous intéresse, le code sera ouvert et libre.
&lt;/p&gt;&lt;p&gt;Pour les technologies choisies :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Front-end : VueJS avec typescript, vuetify, tailwindcss et pinia
&lt;/li&gt;&lt;li&gt;Backend : PHP/Symfony avec certainement API plateform
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Je pourrai faire ce projet en full Symfony avec des templates twig, mais le but est ici de s&#039;exercer à Vue.
&lt;/p&gt;&lt;p&gt;Je vais héberger ce projet sur un raspberry pi à la maison, je ne vais pas mettre en place de docker, des virtual host apache2 suffiront, et je maîtrise bien cette mécanique.
&lt;/p&gt;&lt;p&gt;Le code sera hébergé en 2 repository sur Gitlab.
&lt;/p&gt;&lt;p&gt;Cette première étape fait déjà un article un peu long. J&#039;espère que cela vous intéresse. J&#039;attaquerai la création du front-end dans le prochain billet qui arrivera... quand il pourra :)&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2024-04-26-projet-weekly-cadrage.html" />
    
    <published>2024-04-26T16:21:13Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2023-12-27-symfony-route-rss.html</id>
    <title type="html">Symfony : Une route pour le RSS ?
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Symfony : Une route pour le RSS ?
&lt;/h1&gt;
        &lt;p&gt;Si vous lisez ce blog, vous savez déjà que j&#039;ai un projet personnel autour de l&#039;option Tempo d&#039;EDF. Ce projet est écrit en PHP avec le framework Symfony, que j&#039;apprécie fortement.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/2023-08-30-se-remettre-dans-le-tempo.html&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Se remettre dans le tempo
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;J&#039;ai créé, entre autres, un flux RSS/Atom pour suivre la couleur du lendemain, directement depuis Feeder sur mon Android. J&#039;ai créé un fichier XML à la racine du dossier public, je l&#039;ai référencé dans mon &quot;heade&quot;r afin de le faire découvrir aux navigateurs. Et comme chaque moyen de transmettre l&#039;information Tempo, j&#039;ai créé une page pour indiquer comment l&#039;utiliser.
&lt;/p&gt;&lt;p&gt;Sur cette page, j&#039;indique également le lien vers ce flux, lien généré par le système de routing de Symfony évidemment.
&lt;/p&gt;&lt;p&gt;J&#039;ai cherché des références sur la manière de générer un flux RSS pour le diffuser sur un site, et la manière assez commune est la suivante :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-6&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-6&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;#[Route(&amp;apos;/path-to-feed&amp;apos;, name: &amp;apos;feed&amp;apos;)]
public function feed(): Response

    // le fichier est généré par un service/script externe

    // on récupère le contenu du fichier xml
    $feedContent = file_get_contents(&amp;apos;mon-flux.xml&amp;apos;);

    // on le renvoie comme Response avec le bon header
    return new Response($feedContent, 200, [
        &amp;apos;Content-Type&amp;apos; =&amp;gt; &amp;apos;application/atom+xml&amp;apos;,
    ]);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;De mon point de vue, cette façon de faire manque d&#039;audace et me semble bien lourde. Demander à php de lire un fichier que le navigateur peut interpréter, c&#039;est dommage au niveau des performances.
&lt;/p&gt;&lt;p&gt;D&#039;un autre côté, je ne vois pas mettre un lien en dur directement sur la page, ou utiliser à moitié le système de routing pour générer une URL de base et d&#039;y concaténer le nom du fichier directement dans le twig.
&lt;/p&gt;&lt;p&gt;Alors j&#039;ai testé une autre approche :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-7&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-7&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;#[Route(&amp;apos;/mon-flux.xml&amp;apos;, name: &amp;apos;feed&amp;apos;)]
public function feed(): void
{}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cette route ne fait rien, et n&#039;est même jamais déclenchée vu que le fichier est directement à la racine du dossier public. Il suffit d&#039;autoriser l&#039;extension &quot;.xml&quot;, ou de limiter l&#039;accès à cet unique fichier, dans le &quot;.htaccess&quot; afin de permettre au navigateur de le trouver.
&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;.htaccess ou config de virtualhost Apache2    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule !\.(js|ico|gif|jpg|png|css|xml)$ %{ENV:BASE}/index.php
&lt;/pre&gt;&lt;p&gt;Alors à votre avis, bonne idée ou mauvaise pratique ?
&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2023-12-27-symfony-route-rss.html" />
    
    <published>2023-12-27T19:14:15Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2023-11-28-borne-de-recharge.html</id>
    <title type="html">La borne de recharge
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;La borne de recharge
&lt;/h1&gt;
        &lt;img alt=&quot;&quot; src=&quot;https://darkblog.lhoir.me//assets/2023-11-28-borne-de-recharge/la-borne-de-recharge.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Cet été, nous avons fêté les 3 ans de notre fils. Et quand on est un p&#039;tit gars de 3 ans en 2023, ce que l&#039;on adore par dessus tout, ce sont les voitures. Enfin, tous les véhicules à moteur : camions, autobus, engins de chantier, motos, voitures, avions... Tout ce qui fait vroum ou roule est un émerveillement de chaque instant. Bon, j&#039;ai précisé &quot;p&#039;tit gars en 2023&quot; mais ça aurait pu être la même avec une fille en 1980, cela faisait une belle accroche, je trouve...
&lt;/p&gt;&lt;p&gt;Bref, nous lui avons offert le Graal en matière de voiture pour enfant, à savoir une voiture de police dedans laquelle il peut entrer et circuler un peu partout.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/saint-graal.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/saint-graal.jpg&quot; alt=&quot;Un petit garçon bien heureux dans sa superbe voiture tout de plastique
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Il ne l&#039;a pas lâché de la journée, mais au bout de quelques dizaines de minutes, il nous lança cette terrible question : 
&lt;/p&gt;&lt;blockquote&gt; Bah je la charge où ?
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Quelle diablerie me sortait-il là ? Recharger son nouveau véhicule, comme la voiture de papa. Encore une preuve, s&#039;il en fallait, que nos enfants sont d&#039;excellents observateurs et éponges à émotions/actions que l&#039;on peut leur transmettre dans notre quotidien ! Il avait donc repéré que ce véhicule à propulsion humanoïde possédait une trappe pour ajouter du combustible !
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/la_fameuse_trappe.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/la_fameuse_trappe.jpg&quot; alt=&quot;La fameuse trappe de recharge.
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Complètement pris au dépourvu, je lui ai indiqué un point de recharge imaginaire dans le jardin et il est parti tout heureux dans cette nouvelle quête. Et j&#039;en avais une nouvelle également, il fallait que je crée une borne de recharge pour ce véhicule. Enfin, il fallait, j&#039;avais enfin une idée de projet sympa alors je ne pouvais pas dire non.
&lt;/p&gt;&lt;p&gt;Cet article n&#039;est pas un tutoriel expliquant chaque étape pas à pas, mais plutot le résumé de cette aventure.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; La conception
&lt;/h2&gt;&lt;p&gt;Dans un premier temps, je pensais accrocher une bête boite de dérivation sur un mur extérieur, mettre un autocollant de symbole électrique et un simple fil pour faire l&#039;illusion. Mais ça serait dommage de ne pouvoir jouer que dehors, et puis ce serait plus sympa si la borne était un peu interactive, au moins un bouton... Et un bouton qui déclenche de la lumière, c&#039;est sympa aussi... Après une soirée à y réfléchir, il me fallait mettre mes idées au clair et sur papier.
&lt;/p&gt;&lt;p&gt;Il faudrait que cette borne :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;soit sur pied, pour la déposer n&#039;importe où
&lt;/li&gt;&lt;li&gt;soit autonome électriquement, nécessite une batterie et un système de recharge
&lt;/li&gt;&lt;li&gt;s&#039;allume en branchant un câble de recharge
&lt;/li&gt;&lt;li&gt;possède un bouton qui déclenche la &quot;séquence&quot; de recharge
&lt;/li&gt;&lt;li&gt;une lumière pour indiquer la mise sous tension
&lt;/li&gt;&lt;li&gt;des lumières pour indiquer la recharge
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Un peu de bricolage de bois, de la programmation, de l&#039;électronique et de l&#039;impression 3D, voilà un super projet en perspective :)
&lt;/p&gt;&lt;p&gt;Au cours du processus de création, j&#039;ai mis de côté certaines idées comme l&#039;utilisation d&#039;une vraie prise 200 v comme connecteur. La première raison étant de ne pas donner envie à mon fils de jouer avec les prises de la maison. Pour servir d&#039;interrupteur, le câble à brancher se devait d&#039;être modifié en &quot;cours-circuit&quot;. Je pense que c&#039;est une très mauvaise idée de créer ce genre de câble compatible &quot;prises domestiques&quot; :). J&#039;ai donc fait le choix d&#039;un câble audio Jack comme connecteur, et d&#039;une création 3D pour l&#039;autre bout qui ira dans la voiture.
&lt;/p&gt;&lt;p&gt;Avant de me lancer, j&#039;ai tout de même vérifié que mon idée serait réalisable avec un arduino (ou équivalent chinois), alors j&#039;ai testé un circuit virtuel avec un bout de code écrit avec l&#039;aide de ChatGPT. Je ne sais pas si ces outils, basés sur de l&#039;IA, sont le mal ou non, en tout cas, j&#039;ai codé un programme fonctionnel en moins de 10 minutes sans me replonger dans la doc Arduino. Personnellement, je vois les &quot;IA&quot; à la chat GPT comme des outils supplémentaires et pas comme un remplacement complet des métiers de la tech et de ceux qui utilisent du texte pour travailler. Je sépare le fait de savoir utiliser ces outils de l&#039;expertise de son métier.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; La réalisation
&lt;/h2&gt;&lt;p&gt;J&#039;ai ensuite réuni tout ce dont j&#039;avais besoin pour créer la boite.
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Un arduino nano
&lt;/li&gt;&lt;li&gt;un condensateur 470 microfarads
&lt;/li&gt;&lt;li&gt;un circuit pour convertir le 3,3 v en 5 volts
&lt;/li&gt;&lt;li&gt;un circuit pour gérer l&#039;alimentation et la recharge de la batterie
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;La pièce en rose au milieu est un porte pile imprimé en 3D. C&#039;est un modèle créé par Heliox, une youtubeuse qui partage ses créations et idées de bricolage, mais qui ne correspond plus aux modèles de batteries rechargeables que l&#039;on trouve aujourd&#039;hui. Quand j&#039;aurai plus d&#039;expérience en modélisation, je referai ce genre de création pour le nouveau format, en attendant, j&#039;ai trouvé des portes piles tout fait sur  AliExpress. J&#039;ai globalement réutilisé les composants d&#039;un des projets de Heliox, je mets le lien vers sa vidéo tout en bas de cet article.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/materiel.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/materiel.jpg&quot; alt=&quot;Une bone partie du matériel
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Après le test &quot;virtuel&quot; j&#039;ai réalisé le montage sur une breadboard avant de passer à la soudure. 
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/breadboard.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/breadboard.jpg&quot; alt=&quot;On dirait une bombe avec tous ces fils
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Et voilà le montage une fois terminé dans sa boite.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/montage-electronique.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/montage-electronique.jpg&quot; alt=&quot;Deux circuits electroniques dans une boite de dérivtion avec pleins de fils
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Je ne suis pas vraiment satisfait de ce que j&#039;ai produit en impression 3D et encore moins pour le travail du bois. J&#039;avais pris pas mal de retard dans la création de ce jouet et je commençais à me dire qu&#039;il rejoindrait la longue liste des projets inachevés qui attendent dans mon garage ou dans mon disque dur. J&#039;ai pris quelques mesures sur la trappe et ai modélisé un embout pas tout à fait adapté sous fusion 360, et après 4 ou 5 versions, le résultat était utilisable. Pour le pied, je l&#039;ai créé avec ce qu&#039;il me restait de bois, du coup, il doit y avoir autant de vis que de bois :) Ce n&#039;est pas super propre, je pense qu&#039;avec un peu plus de R&amp;D, j&#039;aurai également fait en sorte de pouvoir recharger la batterie sans ouvrir le boîtier, mais l&#039;important est qu&#039;il adore sa borne.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/connecteur-voiture.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/connecteur-voiture.jpg&quot; alt=&quot;Différentes vues du connecteur
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/ca-fonctionne.jpg&quot;&gt;&lt;img src=&quot;https://darkblog.lhoir.me/assets/2023-11-28-borne-de-recharge/ca-fonctionne.jpg&quot; alt=&quot;Mon fils tout heureux de tester sa borne avec toutes les lumieres
&quot; class=&quot;center rounded bleed bleed&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://gitlab.com/dark-open/kid-charging-system&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le code source du projet
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://wokwi.com/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le site pour tester des montages virtuels
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=tYEFVBXp_HA&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Support de casque en impression 3D par Heliox
&lt;/a&gt;&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2023-11-28-borne-de-recharge.html" />
    
    <published>2023-11-28T17:43:22Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2023-10-30-unset-my-life.html</id>
    <title type="html">Unset my life
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Unset my life
&lt;/h1&gt;
        &lt;img alt=&quot;Un éléPHPant ca trompe énormément&quot; src=&quot;https://darkblog.lhoir.me//assets/2023-10-30-unset-my-life/elephpant.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Un rapide billet pour parler d&#039;un bug, à première vue totalement improbable, au bureau.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Le contexte est la gestion des jours de fractionnement d&#039;un établissement public, dont les congés sont donc gérés de janvier à décembre. Pour rappel, un jour de fractionnement est accordé s&#039;il y au moins 3 périodes de 5 jours de congés consécutifs sur la période de référence, et que les jours déposés sont bien comptabilisés dans la période de référence.
&lt;/p&gt;&lt;p&gt;Par exemple, en 2023, si vous avez 5 jours consécutifs en mars 2023, en juin et septembe 2023, vous &quot;gagnez&quot; 1 jour de fractionnement (de congé quoi).
&lt;/p&gt;&lt;p&gt;Par contre, si vous n&#039;aviez pas soldé vos congés l&#039;année précédente, il se peut que des congés de votre 1re période de 5 jours soient comptabilisés l&#039;année précédente, et vous n&#039;avez donc plus droit à ce congé de fractionnement. Je sais, c&#039;est un peu compliqué, j&#039;en viens au souci dans le code.
&lt;/p&gt;&lt;p&gt;J&#039;étais dans le cas indiqué précédemment et un congé de fractionnement étais tout de même accordé, à tort. Voici grossièrement comment fonctionne le code.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-2&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-2&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;&amp;lt;?php
  // periods est un tableau d&amp;apos;indice numérique et chaque case contient x jours de congés consécutfs
  $periods = retrieveConsecutivePeriods();

  $fiteredPeriods = checkPeriodsWithMinimumDays($periods);

  // cette méthode renvoie la date à laquelle on acquiert le congé de fractionnement, null sinon
  $dayOfSplitting = getDayOfSplitting($fiteredPeriods);

  // si la variable n&amp;apos;est pas nulle le traitement se poursuit
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;En testant un peu, tout fonctionne bien jusque dans la méthode getDayOfSplitting.
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-3&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-3&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;&amp;lt;?php
  public function getDayOfSplitting(array $fiteredPeriods): int
  {
    if (isset($fiteredPeriods[2])) {
      // on fait le traitement
      // dans cet exemple j&amp;apos;ai mis en dur le 2 mais en vrai c&amp;apos;est une variable, qui dans mon cas, donnait 2
    }
  }
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le tableau passé en paramètre ne contenait que 2 éléments et pourtant, il trouve bien l&#039;indice 2 (donc troisième élément du tableau) et réalise le traitement à tort. Si vous êtes un dev avec un peu d&#039;expérience, vous vous doutez sûrement problème, il se situe dans la méthode checkPeriodsWithMinimumDays :
&lt;/p&gt;&lt;br /&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-4&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-4&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;&amp;lt;?php
  public function checkPeriodsWithMinimumDays(array periods) : array {
    foreach ($periods as $key =&amp;gt; $period) {
      if (count($period) &amp;lt; 5) {
        unset($periods[$key]); // houuu ca c&amp;apos;est moche
      }
    } 
  [...]
  }
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le unset a bien supprimé l&#039;élément de mon tableau, mais il n&#039;a pas modifié les indices, donc on se retrouve avec des &quot;trous&quot; dans la suite de chiffres et pour peu que l&#039;élément d&#039;indice 2 persiste, le code produira un beau bug.
&lt;/p&gt;&lt;p&gt;Je n&#039;aime pas l&#039;utilisation du unset dans une boucle pour cette raison, je préfère recréer un tableau qui doit contenir les valeurs à conserver, cela évite bien des erreurs :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-5&#039;);&quot;&gt;&amp;nbsp;&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-5&quot; class=&quot;overflow-auto&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;&amp;lt;?php
  $newTab = [];
  foreach ($periods as $key =&amp;gt; $period) {
    if (count($period) &amp;gt;= 5) {
      $newTab[] = $period;
    }
  }
  [...]
?&amp;gt;
`&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&quot;https://www.flickr.com/photos/atomictaco/49835128682&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Photo par Atomic Tacos
&lt;/a&gt;&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2023-10-30-unset-my-life.html" />
    
    <published>2023-10-30T17:51:15Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2023-10-24-nouveau-format-fichier.html</id>
    <title type="html">Un nouveau format ?
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Un nouveau format ?
&lt;/h1&gt;
        &lt;img alt=&quot;Un logo pour la surcouche gemini x&quot; src=&quot;https://darkblog.lhoir.me//assets/2023-10-24/logo_geminix.png&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Le format gémini est vraiment agréable pour réduire le temps entre l&#039;idée et l&#039;écriture de celle-ci dans une note de blog. Néanmoins, dans ma façon d&#039;imaginer mon système de blog, j&#039;ai rencontré quelques petites limites à ce format simple.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Un nouveau format ?
&lt;/h2&gt;&lt;p&gt;Dans mon idée, le fichier d&#039;un billet de blog doit contenir toutes les données nécessaires à sa publication et sa diffusion. Tout en écrivant le squelette du blog, j&#039;ai ajouté des &quot;méta-données&quot; directement au début de chaque article/fichier, il en ressort 5 lignes commençant par le préfixe &quot;!#&quot; qui ont ces caractéristiques :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Une première ligne contenant le titre de l&#039;article
&lt;/li&gt;&lt;li&gt;Une seconde ligne contenant un résumé/une description du contenu
&lt;/li&gt;&lt;li&gt;Des mots-clefs séparés par une virgule ; utile pour le partage sur les réseaux et le tri des articles par thème
&lt;/li&gt;&lt;li&gt;Une bannière sous la forme d&#039;un lien (local, sans préfixe comme files://) et d&#039;un descriptif pour la balise &quot;ALT&quot;
&lt;/li&gt;&lt;li&gt;Et enfin un champ pour le ou les auteurs sous la forme d&#039;un texte et d&#039;une partie entre &quot;&lt; &gt;&quot; contenant un lien (http, gemini ou mailto) ; chaque auteur étant séparé par une virgule
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Il est a noté que même si seules les 2 premières lignes sont obligatoirement renseignées, toutes les lignes doivent apparaître pour être compatible avec le format. En toute logique, un blog est assez personnel, donc l&#039;auteur devrait toujours être le même, la ligne peut donc rester vide, on sous-entend alors que l&#039;auteur est celui qui tient le blog. Par contre, je me dis qu&#039;il serait dommage de créer un &quot;format&quot; et de ne pas se laisser la possibilité d&#039;écrire à 4 mains voir de donner la parole (l&#039;écriture) à une autre personne sur mon blog. Cette ligne est faite pour cela.
&lt;/p&gt;&lt;p&gt;Voici ce que cela donne pour l&#039;article que vous lisez actuellement :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;!# Un nouveau format et un éditeur de texte
!# Gémnini est un format trop contraignant, il ne laisse pas la place à la créativité des développeurs ? La bonne blague :)
!# gemini, javascript
!# 2023-10-24/logo_geminix.jpg Un logo pour la surcouche gemini x
!# 
A partir de ce point, le reste du fichier est au format gémini, mais avec des fonctionnalités &amp;quot;cachées&amp;quot; dans le système de blog.

&lt;/pre&gt;&lt;p&gt;Pour des raisons de simplicité, j&#039;ai commencé par écrire des articles en laissant l&#039;extension &quot;.gmi&quot; à mes fichiers. Cela m&#039;embête un peu, mes rajouts cassent les normes de ce format. Dans un sens, c&#039;est pratique, car ils restent reconnus par les éditeurs de texte et les navigateurs au protocole gémini, mais cela reste trop brouillon.
&lt;/p&gt;&lt;p&gt;C&#039;est pourquoi j&#039;ai décidé de formaliser, via cet article, ce &quot;format&quot; comme étant du &quot;Gémini X&quot;; non aucune originalité, je ne suis qu&#039;un simple développeur ; avec comme extension de fichier &quot;.gmix&quot;.
&lt;/p&gt;&lt;p&gt;Il faut voir ce format comme une extension du gémini, une simple surcouche, et à l&#039;instar de Sass ou Less pour CSS, le &quot;.gmix&quot; n&#039;est pas destiné à être utilisé comme format de partage direct, mais comme un document d&#039;écriture. Il est nécessaire de passer par une moulinette, libre à vous de faire ce que vous voulez des métadonnées et de garder le reste du document comme fichier au format gémini.
&lt;/p&gt;&lt;p&gt;Il est légitime de se demander si l&#039;utilisation d&#039;un fichier externe n&#039;aurait pas été judicieuse, s&#039;il ne s&#039;agit que de gérer des méta-données. J&#039;ai déjà un fichier qui se crée au moment de la première publication d&#039;un article. Ce fichier reprend les données des 5 premières lignes du format gemini x, mais également un hash de l&#039;article, la date de création, d&#039;édition, le lien vers mastodon, bref un fichier qui gère la vie de l&#039;article publié.
&lt;/p&gt;&lt;p&gt;Finalement, je n&#039;ai pas plus d&#039;explication quant au choix technique d&#039;un seul fichier, et c&#039;est l&#039;avantage de créer seul dans son coin, j&#039;ai fait le choix de ce qui correspond le mieux à mon besoin. Même si cela me ferait plaisir, je ne crée pas ce format avec la prétention qu&#039;il soit largement adopté par la communauté gémini.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Gemini et la créativité
&lt;/h2&gt;&lt;p&gt;À terme, j&#039;aimerais pouvoir partager du code dans des articles, faire des tutos ou juste partager une technique que je trouve intéressante. Pour en avoir plusieurs en cours d&#039;écriture, je me rends compte qu&#039;au format Gemini cela rend les articles affreusement longs, il est difficile de lire l&#039;article entre les gros blocs de code.
&lt;/p&gt;&lt;p&gt;Je voulais avoir une sorte de système de spoiler. En HTML, CSS et un peu de JS, c&#039;est plutôt facile. En gémini par contre... Sauf si l&#039;on détourne un peu l&#039;utilisation du texte libre, les fameux ```. Voici un exemple :
&lt;/p&gt;&lt;pre class=&quot;overflow-auto&quot;&gt;&lt;div class=&quot;spoiler-container code&quot; onclick=&quot;switchSpoiler(&#039;code-1&#039;);&quot;&gt;&amp;#x25BD; SPOILER&lt;span class=&quot;lang&quot;&gt;PHP&lt;/span&gt;&lt;/div&gt;&lt;hr&gt;&lt;code id=&quot;code-1&quot; class=&quot;overflow-auto hide-spoiler&quot; alt=&quot;language PHP&quot; lang=&quot;php&quot;&gt;&amp;lt;?php
    echo &amp;apos;Hello, World!&amp;apos;;
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Au format HTML, vous pouvez cliquer sur le mot spoiler pour afficher ou non le contenu. Si le langage est connu du système, il l&#039;affichera même au début du bout de code (ici PHP).
&lt;/p&gt;&lt;p&gt;Au format Gémini, vous avez un lien vers une capsule qui ne contient que le bout de texte libre et des liens pour revenir à l&#039;article. S&#039;il y avait une notion d&#039;ancre dans GEMINI, cela aurait pu être parfait avec un retour au niveau du lien.
&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Qu&#039;en pensez-vous ?&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2023-10-24-nouveau-format-fichier.html" />
    
    <published>2023-10-24T17:08:37Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2023-08-30-se-remettre-dans-le-tempo.html</id>
    <title type="html">Se remettre dans le Tempo
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Se remettre dans le Tempo
&lt;/h1&gt;
        &lt;img alt=&quot;&quot; src=&quot;https://darkblog.lhoir.me//assets/20230830-metronome.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;La fin de l&#039;été 2023 arrive tout doucement, la première rentrée de notre fils arrivant quant à elle à très grand pas. Je n&#039;ai pas vu passer ces deux derniers mois et cela se ressent sur les publications du blog ; nada. Alors j&#039;écris ce petit billet histoire de reprendre le pli de l&#039;écriture, mais également pour faire un peu de teasing sur les projets (et donc articles) en cours de réalisation. Comme beaucoup, j&#039;adore procrastiner, alors espérons que cela m&#039;aidera à tenir mes &quot;engagements&quot;.
&lt;/p&gt;&lt;p&gt;Voici les projets en cours et que j&#039;aimerais terminer avant cette fin d&#039;année :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Rédaction de 2 articles de blog autour de développement PHP/Symfony (en grande partie écrits, reste à relire et vérifier le code)
&lt;/li&gt;&lt;li&gt;Création d&#039;un format &quot;en surcouche&quot; pour GEMINI (techniquement fait, billet écrit, ça devrait arriver vite)
&lt;/li&gt;&lt;li&gt;Un jouet pour mon fils, regroupant électronique, programmation et bricolage (je le crée et ensuite, je fais le billet.)
&lt;/li&gt;&lt;li&gt;Montée en compétences sur VueJS - c&#039;est déjà en cours avec le boulot -
&lt;/li&gt;&lt;li&gt;Monter et héberger une instance Pleroma afin de jouer le jeu de la décentralisation sur le fediverse
&lt;/li&gt;&lt;li&gt;Monter et héberger une instance PixelFed pour ne plus envoyer de médias à instagram
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Reste à reprendre un bon rythme pour réaliser tout cela tranquillement, sans pression.
&lt;/p&gt;&lt;p&gt;En parlant de rythme, donc de tempo (quelle transition), est-ce que vous savez qu&#039;EDF propose non pas 2, mais 3 options de base pour l&#039;électricité ? La première est le tarif bleu, la seconde est &quot;heures pleines/heures creuses&quot;, et il existe une troisième nommée Tempo.
&lt;/p&gt;&lt;p&gt;Avec cette option, en plus d&#039;être divisé en HC/HP, le tarif du KwH est modulé en fonction de 3 types de journées : bleu, blanc et rouge. Les jours bleus sont très peu chers par rapport au tarif normal, les jours blancs sont légèrement moins cher, et les jours rouges sont beaucoup plus cher, environ 7 fois plus. Avec un calendrier qui se fait jour après jour, EDF peut ainsi inciter les utilisateurs à réguler leur consommation en fonction des pics. Vous êtes informé de la couleur du lendemain à partir de 11 h sur l&#039;application EDF, le site ou par sms, et à partir de 20 h sur votre compteur Linky. Bref, si vous ne chauffez pas votre maison avec de l&#039;électricité et que vous pouvez différer l&#039;utilisation d&#039;appareils énergivores (sèche-linge, four...) c&#039;est une option intéressante financièrement. Je n&#039;ai aucun lien avec RTE, EDF ou autre et vous ne trouverez ici aucun lien de parrainage ou d&#039;affiliation, je ne cherche pas à vous convaincre de passer à cette option, vous faites ce que vous voulez.
&lt;/p&gt;&lt;p&gt;Par contre, soit je n&#039;ai pas compris le fonctionnement des sms, soit le service ne fonctionne pas avec mon numéro, je ne reçois rien. Je trouve que l&#039;information sur le site ou l&#039;application, après une identification, est noyée dans une montagne d&#039;autres données que je ne cherche pas nécessairement à voir au quotidien. Et puis je suis fainéant, taper un login mot de passe à chaque fois, c&#039;est trop long, alors je préfère chercher une alternative. Il existe des sites alternatifs qui partagent l&#039;information, certains le font même à partir de 7 h la veille. Mais soit il y a des traqueurs, soit de la pub, soit l&#039;information est noyée dans les différentes fonctionnalités du site. Cela reste également une grosse page web à charger pour une toute petite information, qui passerait facilement dans un SMS voir un flux RSS ; sérieusement, personne n&#039;y a pensé chez EDF ? De plus, il n&#039;est pas simple de connaître les sources de chacun de ces sites.
&lt;/p&gt;&lt;p&gt;Comme les services ne sont pas à la hauteur de mes exigences, autant le créer moi-même. Cela tombe bien, j&#039;avais justement envie de coder un projet en PHP/Symfony, et RTE propose une API gratuite.
&lt;/p&gt;&lt;p&gt;Je n&#039;en suis qu&#039;au début, le site ne propose pas encore tous les modes de distributions que j&#039;aimerais avoir et il n&#039;est pas très beau. Sur ce dernier point, si vous êtes un webdesigner, ou que vous en connaissez un, ou que vous aimez simplement créer des design légers, modernes et sans utiliser une multitude de dépendances, votre aide sera la bienvenue :)
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://tempo.lhoir.me&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le site du projet Tempo
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://gitlab.com/dark-open/tempo&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le code source du projet
&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://pixabay.com/fr/users/swooshed-933348/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Image par swooshe de Pixabay&lt;/a&gt;&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2023-08-30-se-remettre-dans-le-tempo.html" />
    
    <published>2023-08-30T12:22:03Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2023-06-09-changement-de-cadre.html</id>
    <title type="html">Changement de cadre
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Changement de cadre
&lt;/h1&gt;
        &lt;img alt=&quot;Mon nouvel espace de travail, à la maison !&quot; src=&quot;https://darkblog.lhoir.me//assets/20230609-changement-de-cadre.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Ce vendredi 9 juin 2023 était mon dernier jour en présentiel ! Après une petite semaine de vacances, je commencerai une nouvelle aventure en télétravail total.
&lt;/p&gt;&lt;p&gt;Il parait que les confinements successifs ont donné des envies de changement de vie à bon nombre d&#039;employés dans le monde, je crois que dans mon cas cela s&#039;est fait en deux temps. D&#039;abord, j&#039;ai cherché à quitter la métropole (lilloise). Je n&#039;y vais de toute façon que pour y travailler, avec toutes les galères de transports en commun ou d&#039;embouteillages que cela suppose. (coucou les 1 h 30 pour faire 20 km) En prenant le risque de changer de technologie de développement, j&#039;ai trouvé une entreprise plus proche de chez moi et avec des enjeux qui m&#039;intéressaient bien plus. J&#039;ai certainement laissé passer quelques &quot;belles opportunités professionnelles&quot; mais j&#039;y ai d&#039;autant plus gagné en confort de vie.
&lt;/p&gt;&lt;p&gt;Avant ce changement, je n&#039;avais fait de télétravail qu&#039;en mode &quot;catastrophe&quot;, quand il m&#039;était impossible de me rendre en transport ou en voiture chez le client. Donc du télétravail dans de mauvaises conditions, mais j&#039;avais déjà bien aimé. J&#039;ai passé le premier confinement en inter-contrat et j&#039;ai rejoint l&#039;entreprise que je quitte aujourd&#039;hui en septembre 2020. Ce n&#039;est donc qu&#039;après cette sortie de la métropole que j&#039;ai testé le vrai télétravail avec le second confinement. Mis à part mes années dans l&#039;audiovisuel où &quot;on était mal payé, mais on se marrait bien&quot;, je pense que ce premier test en télétravail a été le meilleur moment dans ma vie professionnelle. Je n&#039;y ai vu que des avantages :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;aucun temps de transport matin et soir
&lt;/li&gt;&lt;li&gt;reprise du sport (marche et renforcement)
&lt;/li&gt;&lt;li&gt;moins de distraction par les collègues et les pauses
&lt;/li&gt;&lt;li&gt;moins de temps avec le casque vissé sur les oreilles, même en écoutant de la musique, du coup la joie de réécouter des albums sur cd avec une vraie chaîne Hi-fi
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Et je ne parle pas du plaisir de pouvoir passer plus de temps avec mon épouse et notre nouveau-né, tous les deux à la maison pendant le congé parental. Je prenais moins de pauses et sincèrement, mes journées étaient tout aussi longues que si j&#039;étais au bureau, transport inclus, mais avec un temps de transition quasi nul.
&lt;/p&gt;&lt;p&gt;Distance oblige, le fonctionnement entre collègues et équipes a dû s&#039;adapter. On avait un point &quot;visio&quot; tous ensemble chaque jeudi après-midi, pour échanger sur les sujets en cours, donner des infos de l&#039;entreprise... Et le reste du temps tout le monde avait pris le pli d&#039;avoir son micro-casque à portée de main pour solliciter ou être sollicité. Le reste du temps : le calme, la concentration sur ce que l&#039;on a à faire. Quand on a la chance d&#039;avoir un job passion, c&#039;est, de mon point de vue, le fonctionnement parfait. Je conçois par contre que ce n&#039;était pas le point de vue de tout le monde dans l&#039;équipe, cela restait un fonctionnement forcé que personne n&#039;avait choisi.
&lt;/p&gt;&lt;p&gt;Le retour à la &quot;normale&quot; a été d&#039;autant plus difficile que l&#039;on avait beaucoup moins de rigueur sur les échanges en présentiel. Beaucoup d&#039;infos s&#039;échangent pendant les pauses clopes ou café, deux choses que je ne fais pas. Je suis sans doute LE collègue un peu chiant, mais j&#039;ai cette mauvaise habitude de rester à mon poste toute la journée pour bosser ou pour faire des pauses en lien avec mon travail. Incroyable n&#039;est-ce pas ? Et sans doute par nostalgie de ces moments passés loin du bureau, on s&#039;est également mis à faire des réunions visios tous en présentiel, vu qu&#039;aucune salle de réunion n&#039;était assez grande et que de toute façon, on aurait tous notre PC et que c&#039;est moins pratique pour partager chacun son tour son écran... Par contre limiter les réunions quand l&#039;un des participants est en télétravail, là ça ne pose pas de problème...
&lt;/p&gt;&lt;p&gt;Bref, suite à un déménagement nous rapprochant de la famille, mais m&#039;éloignant encore du bureau, cela redevenait un non-sens de faire autant de route pour allumer un ordinateur que j&#039;avais chez moi. Alors quand j&#039;ai eu l&#039;opportunité de partir pour du total télétravail, j&#039;ai foncé.
&lt;/p&gt;&lt;p&gt;J&#039;ai conçu mon cocon de travail, mêlant ainsi un autre loisir que j&#039;ai à ce projet de vie : le bricolage. J&#039;ai créé et bricolé ce bureau que vous voyez en début d&#039;article et franchement, c&#039;est gratifiant de savoir que l&#039;on va travailler sur un meuble que l&#039;on a soi-même réfléchi et créé de ses mains.
&lt;/p&gt;&lt;p&gt;Je ne sais pas si le choix de passer au tout distanciel sera parfait, mais je suis content de le faire dans une entreprise où ce fonctionnement est la philosophie de base. Tout le monde est en distanciel, et toute l&#039;organisation se fait en fonction de cela. Il est également possible de se rendre dans des espaces de coworking ou de travailler ponctuellement chez un collègue n&#039;habitant pas trop loin en cas de sentiment d&#039;isolement. C&#039;est assez rassurant d&#039;avoir ce genre de souplesse, l&#039;isolement étant un des facteurs d&#039;échec connu du tout distanciel.
&lt;/p&gt;&lt;p&gt;Je raconterai sans doute ici les péripéties de cette aventure et également sur Mastodon.
&lt;/p&gt;&lt;blockquote&gt; &quot;Quitte à passer la majeur partie de sa vie à travailler avec des collègues, autant bien les choisir&quot; 
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;C&#039;est une phrase que j&#039;ai plusieurs fois entendue et qui me déprimait. Je préfère celle-ci :
&lt;/p&gt;&lt;blockquote&gt; &quot;Quitte à passer la majeure partie de sa vie à travailler, autant dédier le temps restant à ceux avec qui on a choisi de vivre.&quot;
&lt;br /&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2023-06-09-changement-de-cadre.html" />
    
    <published>2023-06-09T19:33:52Z</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2023-04-25-la-capsule-temporelle.html</id>
    <title type="html">La capsule temporelle
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;La capsule temporelle
&lt;/h1&gt;
        &lt;img alt=&quot;Ma capsule temporelle dans une boite Metallica !&quot; src=&quot;https://darkblog.lhoir.me//assets/20230425-la-capsule-temporelle.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Il y a quelques jours, j&#039;ai eu quelques échanges sur Twitter à propos des sorties cinéma, dans le sens notre ressenti sur les séances que l&#039;on a pu avoir dans les salles obscures. Le sujet de base était de parler de nos pires expériences, souvent nous conduisant à sortir pendant la séance, puis cela a dérivé sur ce que l&#039;on considérait comme étant de &quot;bons films&quot;.
&lt;/p&gt;&lt;p&gt;J&#039;ai été surpris de me rendre compte que ma consommation de film au cinéma avait drastiquement chuté ces dernières années, et il me fallait un peu de réflexion que je ne l&#039;aurai cru pour me rappeler des séances les plus &quot;marquantes&quot;, un comble. J&#039;ai pourtant eu un pass illimité juste après mes études, il y a forcément un tas d&#039;anecdotes à raconter.
&lt;/p&gt;&lt;p&gt;Puis je me suis rappelé que j&#039;ai une boite que je considère un peu comme ma capsule temporelle, qui contient pleins des billets de concerts, ciné, festivals en tout genre, et même ma première (et unique) étoile au ski... Bref pas mal de souvenirs au format papier. OK cela ressemble plus à une boite à souvenirs, mais quand on ne l&#039;ouvre que tous les 5 ans ça compte non ?
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/Capsule_temporelle&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Article Wikipédia à propos de la capsule temporelle.
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Bon finalement pas tant de billets de cinéma, en tout cas rien avant 2017, la plupart étant même presque totalement effacés, dommage. Je me suis remémoré mes séances cinématographiques et j&#039;ai terminé l&#039;échange.
&lt;/p&gt;&lt;p&gt;Ce que j&#039;ai pris conscience en ré-ouvrant cette capsule, c&#039;est qu&#039;avec le tout numérique (non, pas digitale pitié !) j&#039;y mets de moins en moins de chose dans cette boite à souvenirs. Je trouve cela dommage, j&#039;adorai avoir ma place de ciné sur ce petit bout de papier avec l&#039;affiche d&#039;un film à l&#039;arrière. On avait une date, un lieu et une activité réalisée en solo ou avec des amis. C&#039;était assez facile à retrouver car non rangé dans des dossiers et sous-dossiers d&#039;un éventuel disque dur ou autre service cloud... Voir un sombre QR code ne menant plus nulle part, dans un bête e-mail.
&lt;/p&gt;&lt;p&gt;Est-ce pour cela que les &quot;sites web&quot; sous le protocole Gemini s&#039;appellent des &quot;capsules&quot; ? Un format de texte et un protocole volontairement simple, tournés vers le texte et donc facile à retrouver après des années ? Peut-être une sorte de compromis entre la frénésie de contenus numériques et la pérennité des livres, format papier.
&lt;/p&gt;&lt;p&gt;Dans tous les cas, ces questionnements, un peu en mode &quot;vieux con&quot;, m&#039;ont donné des idées de séries de billets non-tech pour ce blog, c&#039;est toujours ça.
&lt;/p&gt;&lt;blockquote&gt; Ce billet a un format volontairement &quot;court&quot;, une sorte de &quot;capsule&quot;, un moment de réflexion bref, avec peu de choses à raconter, mais que je tenais à mettre par écrit quelque part. Je regrouperai ce genre de billet sous le tag du même nom (capsule).
&lt;br /&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2023-04-25-la-capsule-temporelle.html" />
    
    <published>2023-04-25T00:00:00</published>

</entry><entry xml:lang="fr">
    <id>https://darkblog.lhoir.me/2023-04-19-hello-world-fr.html</id>
    <title type="html">Hello, World! Mon blog est (enfin) en ligne 
</title>
    <updated>2026-02-02T13:57:51Z</updated>

    <author>
        <name>DarkChyper</name>
        <uri>https://darkblog.lhoir.me/</uri>
    </author>
    <content type="html">
        &lt;h1&gt;Hello, World! Mon blog est (enfin) en ligne 
&lt;/h1&gt;
        &lt;img alt=&quot;Un environnement de travail d&#039;écriture idéal !&quot; src=&quot;https://darkblog.lhoir.me//assets/HomeCatOffice.jpg&quot; class=&quot;center rounded banner&quot; /&gt;&lt;br /&gt;&lt;p&gt;Hourra mon blog est en ligne! Et c&#039;est déjà une petit exploit en soi!
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Génèse
&lt;/h2&gt;&lt;p&gt;Cela fait bien longtemps; traduire ici &quot;longtemps&quot; par &quot;années&quot;; que je voulais tenir un blog. Mettre en forme et partager mes connaissances et mes projets perso ou non. Je me suis toujours dit que c&#039;était un très bon exercice de sythèse et une bonne vitrine de moi même pour les autres et pour moi.
&lt;/p&gt;&lt;p&gt;Comme beaucoup, avant de commencer je me suis posé beaucoup trop de questions. Bien que la plupart étaient assez pertinentes. Quel format, quelles technos, quel design, tout faire à la main ? partir sur du Symfony ou une solution toute faite. Et comment intégrer les principes d&#039;inclusion, gérer la sécurité, où héberger.... et l&#039;écologie dans tout ca ?
&lt;/p&gt;&lt;p&gt;Aujourd&#039;hui j&#039;ai tranché, je commence par faire simple, efficace, mais qui part vite en production (en ligne quoi). De toute façon ce blog évoluera petit à petit, Rome ne s&#039;est pas fait en un jour, et c&#039;est en publiant régulièrement que j&#039;aurai des retours sur ce qui plait, ou non, et que je pourrai améliorer, ou pas.
&lt;/p&gt;&lt;blockquote&gt; Il faut que je m&#039;en tienne au but final de ce blog : écrire pour partager.
&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;h2&gt; Le choix technique
&lt;/h2&gt;&lt;p&gt;Dans un premier temps j&#039;étais parti sur l&#039;idée d&#039;un super site super-dynamique, basé sur Symfony, avec la possibilité de pouvoir faire évoluer tout un tas de choses, connecter des API tierces... Mais cela demande beaucoup de temps, de la grosse maintenance et je fais déjà tout cela 8 heures par jours. Les mois passent, j&#039;ai toujours mieux à faire que de créer un gros projet de zéro, je n&#039;arrive pas à me décider par où commencer, ni me limiter dans les fonctionnalités. Je ne souhaites pas non plus gérer par moi même des aspects comme les commentaires ou des données des utilisateurs alors je vais forcément passer par un système tiers, donc devoir suivre des &quot;normes&quot; de ces tiers, donc lire de la doc...
&lt;/p&gt;&lt;blockquote&gt; Il faut que je m&#039;en tienne au but final de ce blog : écrire pour partager.
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Faisons plus simple. Je commence à suivre une bonne petite liste de blog, dans la tech ou non. J&#039;ai donc l&#039;opportunité de voir différentes façon de faire et j&#039;aime beaucoup le blog de Flozz. Il est agréable à lire, rapide à charger. Il est basé sur Pelican, un système de site web statiques.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blog.flozz.fr/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le blog de Flozz
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://getpelican.com/&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le site de l&#039;outil Pelican
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;J&#039;ai commencé par me renseigner sur Pelican, sur le fonctionnement, tester un peu en local. Mais encore une fois beaucoup de possibilités, beaucoup de fioritures, il faut créer un thème complet ou en choisir un à adopter parmis une liste assez longue. En plus l&#039;outils est en python, je connais assez mal ce langage. Du coup oui c&#039;est évolutif mais cela demandera du temps avant de publier... J&#039;ai continué à laisser passer des mois avec ce sujet en attente.
&lt;/p&gt;&lt;p&gt;Il faut que je me rende à l&#039;évidence, si la création de ce blog n&#039;est pas très simple, je ne le ferais jamais.
&lt;/p&gt;&lt;p&gt;Puis, grâce à un toot de Flozz, j&#039;ai découvert le projet Gemini. Non, pas celui des capsules spatiales, mais celui des capsules web ! un protocole/format de fichier très rudimentaire qui se focalise sur l&#039;écriture et la simplicité avant tout ! Hey pas mal ça, il faut que je creuse.
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fr.wikipedia.org/wiki/Gemini_(protocole)&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;L&#039;article Wikipedia sur le protocole Gemini
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Depuis que vous lisez ce tout premier article vous avez constaté que je parle beaucoup, à l&#039;écrit. Enfin je fais de longues phrases, je digresse souvent, donc le blabla devrait prendre une place importante dans mes articles. Du coup j&#039;aimerai bien baser mon blog sur cette technologie &quot;Gemini&quot;. Et en même temps il y a certains aspects techniques que je n&#039;aime pas trop dans cette simplicité ! Où sont les images ? OK avec Gemini on revient beaucoup dans les années 90 avec un web accès sur la lecture seule, mais il y avait tout de même un peu d&#039;images d&#039;illustration.
&lt;/p&gt;&lt;p&gt;Et en creusant, j&#039;ai découvert le blog de ploum avec son article &quot;La fin d’un blog et la dernière version de ploum.net&quot;. 
&lt;/p&gt;&lt;blockquote&gt; Super je découvre un blog par la fin, bravo le veau !
&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Je ne vais pas rentrer dans les détails, mais j&#039;ai adoré le côté &quot;Gemini first&quot;, et la conversion des fichiers .gmi vers du HTML à peine plus compliqué, mais qui a au moins le mérite d&#039;afficher les images ! Tout est simple, chaque page est indépendante, le css est très léger, aucun traqueur, PAR-FAIT ! En fait, j&#039;ai l&#039;impression que Ploum, Lionel Dricot de son vrai patronyme, a déjà réalisé toute la réflexion que je pouvais avoir sur le sujet, et il propose une solution viable. 
&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://ploum.net&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le blog de Ploum
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;gemini://ploum.net&quot; rel=&quot;external&quot; class=&quot;external&quot;&gt;Le même blog mais via le protocole Gemini
&lt;/a&gt;&lt;/p&gt;&lt;p&gt;OK le code est en Python, je ne connais toujours pas super bien ce langage mais suffisemment pour comprendre le fonctionnement. Et puis il y a des choses qui me manquent encore comme les tags et les commentaires déportés. Qu&#039;à cela ne tienne, je vais m&#039;inspirer fortement de son travail mais le faire à ma sauce, et en PHP. Et pour faire cette transformation, je vais me baser sur 3 questions que l&#039;on m&#039;a confié il y a peu :
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Qu&#039;est-ce que je veux améliorer
&lt;/li&gt;&lt;li&gt;Qu&#039;est-ce que Je veux ne pas perdre
&lt;/li&gt;&lt;li&gt;Qu&#039;est-ce que je suis pret à perdre pour y arriver
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Bon a priori j&#039;ai fini par y arriver puisque vous m&#039;avez lu jusqu&#039;ici.
&lt;/p&gt;&lt;br /&gt;&lt;h2&gt; Syndrome de la page blanche (et de l&#039;imposteur)
&lt;/h2&gt;&lt;p&gt;Reste maintenant à trouver de l&#039;inspiration pour les articles, et surtout d&#039;arrêter de me dire que tout a déjà été écrit, que l&#039;on attend de moi un niveau de connaissances de dingue pour oser partager quoique ce soit en ligne.
&lt;/p&gt;&lt;p&gt;Pour le moment je commence avec des articles en français uniquement. Commençons petit et voyons la suite.
&lt;/p&gt;&lt;p&gt;Et il faudra aussi que je travaille sur l&#039;aspect clair et concis, cette introduction est déjà trop longue n&#039;est-ce pas ?&lt;/p&gt;
    </content>
    <link rel="alternate" type="text/html" href="https://darkblog.lhoir.me/2023-04-19-hello-world-fr.html" />
    
    <published>2023-04-19T00:00:00</published>

</entry>
</feed>