Les codes QR sont souvent utilisés à titre publicitaire pour transmettre l'adresse de sites internet, sur des affiches ou des papillons. Ils peuvent aussi véhiculer d'autres types d'information, comme une configuration Wi-Fi, une vCard, une localisation GPS. Si on est capable de les générer dynamiquement, on peut même penser à un code à durée limitée, ou un témoin horaire... et là ça devient très intéressant.
Pour afficher un code QR dynamique, il faut utiliser un écran qui soit facile à lire avec la caméra d'un téléphone portable. Les écrans lumineux ne sont pas idéaux pour les caméras numériques, mais les écrans e-paper sont eux parfaits. Voici par exemple ce qu'on pourrait trouver dans les chambres d'un hôtel qui doit changer régulièrement le code de son WiFi pour éviter que les voisins n'en abusent:

Un code QR pour se connecter facilement au réseau WiFi visiteur
Pour vous faciliter la vie, nous avons choisi d'ajouter directement dans notre contrôleur e-Paper, le Yocto-Display-ePaper-C, le code permettant de générer des codes QR. Du coup, pas besoin d'intégrer une librairie supplémentaire à votre projet, il suffit d'un appel à la fonction drawQRCode(). Le code utilisé pour afficher le message ci-dessus est le suivant:
pwd = "DKrhxZnYUB2a4b52jt" # note: escapez \;,": le cas échéant
qrContent = "WIFI:T:WPA;S:{0};P:{1};;".format(ssid,pwd)
dispLayer.selectFont("Large.yfm")
dispLayer.drawText(145, 55, dispLayer.ALIGN.TOP_LEFT, "Scan code to join")
dispLayer.drawText(145, 90, dispLayer.ALIGN.TOP_LEFT, ssid)
dispLayer.selectFont("Medium.yfm")
dispLayer.drawText(145, 130, dispLayer.ALIGN.TOP_LEFT, "password: " + pwd)
dispLayer.drawQRCode(15, 50, dispLayer.QRMODE.BYTES_ECCL, 4, qrContent)
Codes QR supportés par Android (10+) et iOS (11+)
Dans un code QR, vous pouvez mettre par exemple:
- Une URL, que le téléphone proposera d'ouvrir dans un navigateur:
https://site.com/adresse?paramètres
- Une configuration WiFi, que le téléphone proposera d'activer:
WIFI:T:WPA;S:nom_réseau;P:mot_de_passe;;
- Un numéro de téléphone, que le téléphone proposera d'appeler:
tel:+123456789
- Un SMS que le téléphone proposera d'envoyer:
sms:+123456789?body=hello%20there
- Un mail que le téléphone proposera d'envoyer:
mailto:user@domain.com?subject=important&body=Hello!
- Une carte de visite, que le téléphone proposera d'ajouter au carnet d'adresses:
BEGIN:VCARD...
- Une localisation précise, par coordonnées GPS:
geo:46.22662,6.14034
D'autres messages spécifiques à des application particulières sont supportés, par exemple un lien vers un groupe Signal ou un groupe WhatsApp, encodés comme une URL particulière. Ces URLs utilisent le mécanisme des App Links sous Android (liens universels sous iOS) que le téléphone redirige automatiquement vers la bonne application si elle est installée, et sur la page d'installation de l'application dans le cas contraire.
Taille des codes QR
Le plus petit code QR possible est dessiné dans un carré de 21x21 points, et ne peut contenir que 17 octets d'information dans le meilleur des cas. Le plus grand code QR supporté par notre contrôleur d'écran e-Paper fait 145x145 points, et peut contenir jusqu'à 2KB environ.
En pratique, on affiche rarement un code QR à l'échelle 1:1, mais on le grossit pour en faciliter la lecture à distance. C'est à cela que sert l'avant-dernier paramètre de la méthode drawQRCode(): dans notre exemple ci-dessus, chaque point du code QR est affiché par un carré de 4x4 pixels.
A l'usage, on choisit en général une zone de l'écran à allouer au code QR, et on aimerait qu'il y soit centré avec le meilleur grossissement possible. On peut utiliser le code suivant pour cela:
qrMode = dispLayer.QRMODE.BYTES_ECCL
qrSize = dispLayer.drawQRCode(x, y, qrMode, 0, text)
zoom_max_x = w // (qrSize + 8)
zoom_max_y = h // (qrSize + 8)
zoom = min(zoom_max_x, zoom_max_y, 16)
zoomed_size = qrSize * zoom
x += (w - zoomed_size) // 2
y += (h - zoomed_size) // 2
dispLayer.drawQRCode(x, y, qrMode, zoom, text)
Ce code utilise une astuce: lorsqu'on appelle la méthode drawQRCode() avec un grossissement nul, rien n'est affiché, mais la fonction retourne la taille du QR code en points. On peut alors calculer le grossissement optimal et les paramètres de centrage, en gardant 4 points blancs tout autour du code QR comme demandé par la norme (même si en pratique les téléphones en ont souvent besoin de moins).
Paramètres avancés
Nous avons pour l'instant passé sous silence le 3e paramètre de la méthode drawQRCode(): il s'agit du mode d'encodage du code QR. Ce paramètre mystérieux définit deux choses: le jeu de caractères utilisé pour stocker le contenu, et le niveau de correction d'erreur souhaité.
Le jeu de caractères le plus couramment utilisé est le mode BYTES, qui permet d'inclure n'importe quel octet dans le contenu. Dans quelques cas particuliers où vous n'auriez besoin ni de minuscules, ni de symboles spéciaux autres que +-*/.:%$ et l'espace, vous pouvez utiliser le mode UPCASE, qui économise environ 30% de points, ce qui peut permettre de grossir un peu plus le code. Mais il est très rare que cela soit applicable: vous avez par exemple le droit d'écrire HTTPS://SITE.COM, mais le reste de l'URL doit respecter la casse.
Le niveau de correction d'erreur détermine la redondance des informations dans le code, permettant d'assurer le décodage du code même si des points sont cachés par des salissures, ou des dessins intentionnellement surimposés. Il existe quatre niveaux, permettant une restauration de 7% à 30% de points manquants, au prix de 20% à 110% de points supplémentaires dans le code, donc d'un accroissement de la taille du code:
| Niveau
| Capacité nominale de restauration | Taille relative des côtés du code QR |
|---|---|---|
| ECCL (Bas) | ~7% | référence |
| ECCM (Moyen) | ~15% | +10% |
| ECCQ (Quart) | ~25% | +30% |
| ECCH (Haut) | ~30% | +45% |
Comme on le voit, ajouter de la redondance pour corriger des points manquants affecte significativement la taille du code QR. Si l'espace alloué au code sur l'écran est fixe, ajouter de la redondance conduira à utiliser des points plus petits, plus susceptibles d'être mal lus à distance. C'est donc un compromis que vous devrez gérer en fonction de votre application. Si vous n'avez pas particulièrement besoin de tolérance aux salissures, et si vous ne dessinez pas par dessus votre code QR, un niveau de correction bas ou moyen est souvent préférable.
Vitesse d'affichage
Les calculs nécessaires à l'affichage d'un grand code QR ne sont pas négligeables, en raison des calculs de correction d'erreur et de la phase d'optimisation durant laquelle il faut tester différents masques pour trouver celui qui minimise les risques d'erreur de lecture. Nous avons basé notre implémentation sur le code de Richard Moore publié sous licence MIT, lui-même dérivé du classique Project Nayuki, aussi en licence MIT. Nous avons considérablement retravaillé le code pour qu'il fonctionne efficacement sur le petit MCU 16bit utilisé par nos modules. Au final, vous pourrez afficher un QR code de 80 caractères en une fraction de seconde, et un QR code de 600 bytes en une seconde environ.
Conclusion
Le support natif pour l'affichage des codes QR est une corde de plus à votre arc si vous avez opté pour le Yocto-Display-ePaper-C. Assurez-vous simplement d'installer un firmware version 76629 ou supérieur, pour qu'il inclue la génération des codes QR, et d'utiliser une librairie de programmation à jour pour qu'elle inclue la méthode drawQRCode. Nous aurons l'occasion de revenir sur des exemples concrêts d'utilisation de codes QR dynamiques dans des prochains articles.
Pour finir, notez que les fonctions d'affichage de codes QR fonctionneront aussi sur les grands écrans OLED Yoctopuce comme le Yocto-MaxiDisplay-C avec un firmware à jour, même si leur utilité y est moindre.
