Vous voulez savoir comment enregistrer en toute sécurité (et assez simplement) des millions d'appareils IoT dans votre environnement cloud, stocker correctement leurs flux de données à haut débit et mettre en place des visualisations en aval, le tout avec des exemples de code complets ? Entrons dans le vif du sujet ! Cet article couvre l'ensemble du workflow, de l'autorisation des appareils IoT au streaming des données ; le stockage et la visualisation seront traités dans un second article. Nous utiliserons AWS comme fournisseur cloud et des Raspberry Pi équipés de capteurs de température en guise d'appareils IoT.

Bonnes pratiques IoT en production : mise en œuvre sur AWS
Vue d'ensemble
Cette présentation se découpe en plusieurs sections :
- Configuration logicielle et matérielle du Raspberry Pi
- Vue d'ensemble du provisioning de credentials uniques par appareil
- Création concrète d'un template de provisioning et d'un certificat de bootstrap
- Test de connectivité des appareils et streaming des données de température
- Stockage des données streamées (traité dans la Partie 2)
- Visualisation des données streamées (traité dans la Partie 2)
Le programme est chargé, alors commençons ! Pour suivre cet article, il vous suffit d'avoir une expérience de base de Bash et Python, une compréhension élémentaire de la console AWS, et une grande tasse de café pour tenir la distance.
Configuration logicielle et matérielle du Raspberry Pi
Commencez par mettre en service plusieurs Raspberry Pi (j'utiliserai des Pi 3). Je recommande l'imageur Raspbian OS pour automatiser l'installation de l'OS sur les cartes microSD. Une fois arrivé sur le bureau et après avoir mis à jour votre appareil, exécutez la commande suivante pour installer le SDK spécifique à AWS IoT :
pip3 install -U awsiotsdk
Il est important de bien comprendre ce package avant d'aller plus loin :
1. Pourquoi le SDK IoT est-il distinct du SDK boto3 à usage général ? Boto3 repose sur HTTP, un protocole pratique pour exécuter rapidement la plupart des actions AWS. En revanche, HTTP n'est pas adapté à l'envoi de messages sur des connexions de longue durée présentant une forte probabilité de coupures intermittentes, où les données circulent principalement de l'appareil vers le cloud. MQTT, le protocole utilisé par le SDK IoT, est conçu spécifiquement pour les cas d'usage IoT : il simplifie nettement la publication fréquente de messages et leur réception ponctuelle, malgré des conditions de connectivité difficiles.
2. Le package awsiotsdk correspond à la v2 du SDK AWS IoT. C'est une entité distincte du package v1 AWSIoTPythonSDK, au nom similaire. La quasi-totalité des tutoriels publiés à ce jour sur AWS IoT s'appuient sur la v1 du SDK IoT, qui complique malheureusement la mise en œuvre d'une approche d'enregistrement à l'échelle de la production. La v2 simplifie également la publication et la réception de messages : nous travaillerons donc avec la dernière version.
Maintenant que les SDK AWS requis sont installés sur votre Raspberry Pi, vous devez y connecter un capteur de température numérique. Je recommande ce capteur DS18B20 si vous souhaitez suivre l'article étape par étape.
Vous aurez également besoin du matériel suivant pour relier le capteur à votre Raspberry Pi :
Câbles de pontage pour breadboard
Kit de résistances assorties (il nous faut une résistance de 4,7 kΩ)
Si vous devez patienter quelques jours pour recevoir ces éléments, n'hésitez pas à poursuivre la lecture : un script permettant de simuler le streaming de valeurs de température sera également fourni. Si vous disposez déjà du matériel, les cinq premières minutes du tutoriel ci-dessous expliquent comment connecter le capteur au Raspberry Pi et vérifier qu'il reçoit bien les valeurs de température :
Tutoriel capteur de température DS18B20 sur Raspberry Pi
En complément du processus décrit dans ce tutoriel, je recommande d'ajouter ce qui suit dans /etc/modules pour que les modules onewire soient chargés au démarrage, plutôt que de devoir lancer modprobe après chaque redémarrage :
w1-gpio
w1-therm
Vue d'ensemble du provisioning de credentials uniques par appareil
Parmi les nombreux articles consacrés à AWS IoT, la plupart s'appuient sur la v1 du SDK IoT pour présenter un exemple jouet où un seul appareil est enregistré sur un compte cloud. Le processus décrit consiste généralement à créer un certificat avec les permissions AWS IoT associées, puis à placer les fichiers de certificat sur l'appareil afin qu'il puisse réaliser des appels d'API IoT pour streamer ses données vers le cloud.
Or ces exemples sont peu applicables : les cas d'usage IoT réels impliquent des milliers, voire des millions d'appareils streamant vers un environnement cloud. Chaque appareil d'une telle flotte doit disposer d'un jeu de credentials qui lui est propre, afin que si l'un d'eux ou ses credentials AWS sont compromis et utilisés à des fins illégitimes (par exemple pour streamer de fausses données vers votre plateforme), ce jeu de credentials puisse être désactivé sans impacter les autres appareils de la flotte.
Comment simplifier au maximum la création de credentials propres à chaque appareil ? Peut-on procéder sans créer à l'avance des millions de certificats ni coordonner leur déploiement individuel sur chaque appareil pendant la fabrication ? Et à l'inverse, peut-on procéder sans obliger le fabricant à émettre des appels d'API vers votre environnement pour créer un nouveau certificat à la demande lorsqu'un appareil sort de la chaîne de production pour être bootstrappé avec son logiciel et ses credentials ? Ces approches sont à éviter : elles sont complexes, sources d'erreurs et imposent une charge inutile au fabricant.
Heureusement, il existe une solution simple, dont la mise en œuvre est facilitée par la v2 du SDK IoT. L'attribution à grande échelle de credentials uniques par appareil peut se faire en créant deux entités dans la console AWS IoT : (1) un fleet provisioning template, et (2) un certificat de bootstrap à placer sur tous les appareils. Le workflow ci-dessous explique le processus :
- Un seul certificat IoT est créé et placé sur l'ensemble des appareils IoT. Ce certificat, dit certificat de bootstrap, est associé à une politique de permissions qui autorise uniquement l'appareil à (a) émettre une requête de création d'un certificat propre à l'appareil et récupérer ces credentials si la requête aboutit, et (b) s'inscrire dans le registre IoT des appareils. Cette requête peut éventuellement transmettre un identifiant unique pour l'appareil, comme un numéro de série.
- À la réception de la requête de création de certificat, la plateforme AWS IoT crée un nouveau certificat et transmet les fichiers associés à l'appareil. Les permissions IoT associées à chaque nouveau certificat, ainsi que les différents attributs liés à votre appareil nouvellement enregistré, reposent sur un template que vous créez et qu'AWS appelle le fleet provisioning template.
Ce template associe des attributs aux appareils nouvellement enregistrés, par exemple {"DeviceType": "RaspberryPi"}, et permet en outre que tous les certificats uniques par appareil soient associés à une même politique de permissions, capable malgré tout de définir des permissions propres à chaque appareil.
Par exemple, l'unique politique IoT du template pour les appareils enregistrés peut être conçue pour autoriser l'appareil nommé sensor123 à publier uniquement vers le topic IoT sensors/temp/sensor123, l'appareil sensor456 à publier uniquement vers sensors/temp/sensor456, et ainsi de suite. Autrement dit, la politique de permissions du fleet provisioning template vous évite d'avoir à créer une nouvelle politique pour chaque nouvel appareil et son certificat. Cette approche permet aussi de déployer des changements de permissions sur l'ensemble de la flotte IoT via une seule mise à jour de politique.
3. Le processus de création d'un certificat d'appareil peut éventuellement être conditionné par ce qu'AWS appelle un pre-provisioning hook. Il s'agit d'une fonction Lambda que vous écrivez et qui peut exiger qu'un identifiant unique soit fourni dans la requête de certificat, afin de le confronter à une whitelist (par exemple, la liste de tous les numéros de série fabriqués) et/ou à une blacklist (par exemple, la liste des numéros de série associés à des appareils compromis ou abusifs).
4. Si la requête est approuvée, les fichiers de certificat de l'appareil lui sont transmis pour le streaming des données, et l'appareil est inscrit dans le registre IoT avec les attributs définis par le template. Le certificat de bootstrap n'est alors plus nécessaire pour l'appareil.
Avec ce workflow, le fabricant d'appareils IoT n'a plus qu'à fournir à chaque appareil le certificat de bootstrap. Le certificat unique permettant le streaming peut être créé et obtenu immédiatement dans l'usine, ou plus tard, une fois l'appareil entre les mains de l'utilisateur final. Quel que soit le moment où les credentials sont obtenus, le fabricant bootstrappe sur l'appareil le logiciel que vous fournissez ; celui-ci exécute le processus de création de certificat basé sur le fleet provisioning template à chaque démarrage de l'appareil, dès qu'une connexion Internet est disponible et qu'aucun certificat d'appareil n'est détecté.
Exemple pratique d'utilisation du fleet provisioning template et du certificat de bootstrap
Cela fait beaucoup d'informations à digérer, je le sais ; tout devrait s'éclaircir une fois que vous aurez mis le processus en pratique.
Voici un exemple complet et fonctionnel de configuration de votre registre IoT, avec des appareils ajoutés via un fleet provisioning template et un certificat de bootstrap. Nous utiliserons ensuite les certificats d'appareil créés pour streamer les données de température vers la plateforme AWS IoT.
Commencez par accéder au service AWS IoT Core. Si vous n'avez jamais utilisé ce service, vous serez accueilli par une page d'assistant proposant Onboard a device ou Onboard many devices. Cet assistant nous guidera à travers le processus du fleet provisioning template, mais en raison d'une particularité de cet assistant, mieux vaut quitter cet écran et créer d'abord le certificat de bootstrap.
Dans le menu de gauche, allez sur Secure → Certificates et cliquez sur Create, puis choisissez One-click certificate creation. Cela créera immédiatement un nouveau certificat que nous utiliserons comme certificat de bootstrap. Veillez à télécharger le certificat (cert.pem), la clé privée (private.key) et l'autorité de certification racine (suivez le lien Download et enregistrez le fichier AmazonRootCA1.pem), puis cliquez sur Activate pour activer le certificat :

Une fois le certificat activé et les clés téléchargées, cliquez sur Attach a policy. Nous allons créer une politique qui transformera ce certificat en certificat de bootstrap. Depuis l'écran Add authorization to certificate, cliquez sur Create New Policy et créez une politique nommée IoT_Bootstrapping_Certificate. Cette politique accordera les permissions de publier, de s'abonner et de recevoir des messages sur deux topics réservés AWS utilisés pour la création de certificats et le processus de fleet provisioning template :

Veillez à remplacer la région, l'ID de compte et le templateName par les valeurs propres à votre compte
Action: iot:Connect
Resource ARN: *Action: iot:Publish
Action: iot:Receive
Resource ARN: arn:aws:iot:us-west-2:123456789012:topic/$aws/certificates/create/*Action: iot:Publish
Action: iot:Receive
Resource ARN: arn:aws:iot:us-west-2:123456789012:topic/$aws/provisioning-templates/SensorTemplate/provision/*Action: iot:Subscribe
Resource ARN: arn:aws:iot:us-west-2:123456789012:topicfilter/$aws/certificates/create/*Action: iot:Subscribe
Resource ARN: arn:aws:iot:us-west-2:123456789012:topicfilter/$aws/provisioning-templates/SensorTemplate/provision/*
Cliquez sur Create. Une fois la politique de certificat créée, retournez sur le certificat que vous avez créé et attachez-lui cette politique :


Maintenant que nous disposons d'un certificat de bootstrap prêt pour nos appareils, revenons à l'assistant de fleet provisioning template. Pour cela, cliquez sur Onboard → Get started.
Dans l'assistant, choisissez Onboard many devices, puis renseignez les informations suivantes :

- Template name : SensorTemplate
- Provisioning role : créez un rôle nommé IoTProvisioningRole et associez-le à la politique managée par AWS AWSIoTThingsRegistration. Ce rôle permet à la plateforme AWS IoT d'enregistrer de nouveaux appareils lors de leur connexion.
- Dans un scénario réel, vous écririez une fonction Lambda servant de pre-provisioning hook pour valider un numéro de série avant d'autoriser la création d'un certificat d'appareil ; par souci de concision, nous laissons cette option de côté. Vous pourriez par exemple l'utiliser pour comparer un numéro de série à des tables DynamoDB de numéros blacklistés et de numéros connus. Voici un exemple simple de ce à quoi cela pourrait ressembler :
def lambda_handler(event, context):
serial = event["parameters"]["SerialNumber"] # Implement serial number validation functions
if is_valid_serial(serial) and not is_blacklisted(serial):
return {"allowProvisioning": True} return {"allowProvisioning": False}
- Cochez l'option facultative Use the AWS IoT registry to manage your device fleet. Cela vous permettra de visualiser les appareils associés dans la console web IoT, ainsi que de pousser des mises à jour de l'état de l'appareil ou de son logiciel.
Sur la page suivante, nous allons définir une politique IoT associée au template, qui donne à nos appareils les permissions de publier et de recevoir des messages depuis un topic IoT propre à chaque appareil. Nous créerons cette politique IoT à l'aide d'une thing policy variable. Les thing policy variables permettent aux appareils de publier ou de recevoir des messages sur un topic IoT propre à chaque appareil. Dans cet exemple, les appareils publieront et s'abonneront à un topic basé sur BuildingName, Location (au sein du bâtiment) et ThingName :

Action: iot:Connect
Resource ARN: arn:aws:iot:us-west-2:123456789012:client/${iot:Connection.Thing.ThingName}
Action: iot:Publish
Action: iot:Receive
Resource ARN: arn:aws:iot:us-west-2:123456789012:topic/temperature/${iot:Connection.Thing.Attributes[BuildingName]}/${iot:Connection.Thing.Attributes[Location]}/${iot:Connection.Thing.ThingName}
Action: iot:Subscribe
Resource ARN: arn:aws:iot:us-west-2:123456789012:topicfilter/temperature/${iot:Connection.Thing.Attributes[BuildingName]}/${iot:Connection.Thing.Attributes[Location]}/${iot:Connection.Thing.ThingName}
Sur la page suivante, définissez les paramètres de votre registre AWS IoT — ce sont les attributs assignés à chaque appareil nouvellement provisionné :

- Préfixe du nom de Thing : sensor_
- Créez un nouveau Thing Type TemperatureSensor avec un Searchable Thing Attribute Location (par exemple loft, downstairs) et BuildingName (par exemple home417)
- Créez les attributs non searchables suivants : DeviceType (par exemple RaspberryPi) et ModelNumber (par exemple 3)
Sur l'écran final, après avoir cliqué sur Create template, sélectionnez le certificat de bootstrap créé précédemment, cliquez sur Attach policy, puis sélectionnez Enable template. Cette association permet aux appareils utilisant le certificat de bootstrap de s'appuyer sur ce template pour obtenir un certificat d'appareil disposant des permissions nécessaires à la publication de messages vers un topic IoT spécifique au nom de l'appareil. En plus d'obtenir un certificat, l'appareil utilise également le fleet provisioning template pour s'inscrire dans le registre IoT et se voir attribuer les attributs que nous avons définis.

Pour récapituler, nous venons de réaliser ce qui suit :
- Création d'un certificat de bootstrap, associé à une politique qui permet uniquement à un appareil utilisant ce certificat d'émettre, via un fleet provisioning template, une requête pour (1) un nouveau certificat propre à l'appareil et (2) son inscription dans le registre IoT avec les attributs par défaut.
- Les certificats d'appareil créés pour les appareils nouvellement enregistrés sont associés à une politique IoT qui autorise l'appareil à publier et à recevoir des messages depuis un topic IoT qui lui est propre.
La préparation côté service IoT est presque terminée. Il ne reste plus qu'à mettre à jour le fleet provisioning template pour qu'il accepte et exige la fourniture des attributs searchables lors de la requête de provisioning. Retournez sur SensorTemplate et ajoutez ce qui suit au JSON du template :
# Add "BuildingName" and "Location" within "Parameters"
{
"Parameters": {
"SerialNumber": {
"Type": "String"
},
"BuildingName": {
"Type": "String"
},
"Location": {
"Type": "String"
},
"AWS::IoT::Certificate::Id": {
"Type": "String"
}
}
}# Reference these attribute parameters within "thing": "Properties"
"Properties": {
"AttributePayload": {
"DeviceType": "RaspberryPi",
"ModelNumber": "3",
"BuildingName": {
"Ref": "BuildingName"
},
"Location": {
"Ref": "Location"
}
},
"ThingGroups": [],
Nous avons effectué pas mal de modifications dans la console IoT ! Vérifions à présent que le certificat de bootstrap et le fleet provisioning template fonctionnent, à l'aide d'exemples de code concrets.
Test de connectivité des appareils et streaming des données de température
Copiez les fichiers de certificat téléchargés dans un dossier sur vos RPi, puis créez le fichier config.ini ci-dessous avec les valeurs adéquates. En plus de mettre à jour les chemins des fichiers de certificat, vous devrez récupérer l'IoT Endpoint de votre compte depuis la page Settings de la console AWS IoT :
# Set the path to the location containing your bootstrap certificates (root, private, claim certificate)
SECURE_CERT_PATH = /home/pi/iot_certs/
# Specify the names for the root cert, provisioning claim cert, and the private key.
ROOT_CERT = AmazonRootCA1.pem
CLAIM_CERT = <YOURCERT>-certificate.pem.crt
SECURE_KEY = <YOURCERT>-private.pem.key
# Set the name of your IoT Endpoint
IOT_ENDPOINT = <YOUR_ENDPOINT>-ats.iot.us-west-2.amazonaws.com
# Set the IoT topic name
IOT_TOPIC = temperature/${iot:Connection.Thing.Attributes[BuildingName]}/${iot:Connection.Thing.Attributes[Location]}/${iot:Connection.Thing.ThingName}
# Set the IoT provisioning template name
PROVISIONING_TEMPLATE_NAME = SensorTemplate
Exécutez ensuite le script suivant, qui utilise votre certificat de bootstrap pour obtenir un certificat d'appareil (enregistré dans iot_certs/permanent_cert/) et inscrit l'appareil dans le registre IoT. Avec le paramètre -l, définissez l'attribut Location correspondant à l'emplacement de votre appareil dans votre maison. Par exemple :
./connect_rpi_to_iot_core.py -c config.ini -b home417 -l loft
Il se passe beaucoup de choses ici, je vous recommande donc vivement de prendre le temps de parcourir le code pour bien comprendre l'enchaînement des appels d'API du SDK IoT. Si tout est correctement configuré, vous verrez le script se terminer en affichant Success à l'écran, un jeu de trois fichiers de certificat dans permanent_cert/, ainsi qu'un nouveau fichier perm_config.ini dans ce dossier pour les fichiers de certificat de l'appareil.
Vous remarquerez qu'à mesure que vous ajoutez vos RPi avec ce script, de nouveaux certificats apparaissent dans la console IoT, tous associés à l'unique politique IoT que nous avons définie dans le fleet provisioning template, qui autorise la publication et l'abonnement aux messages sur un topic basé sur BuildingName, Location et ThingName.
Chaque appareil ajouté par le script est enregistré avec le ThingName sensor_{UUID}, où UUID est un identifiant unique fourni par /etc/machine-id sur l'appareil. Ainsi, chaque appareil publiera ses messages sur son propre topic IoT. Dans un scénario IoT réel, vous pourriez utiliser le numéro de série de l'appareil comme ThingName unique.
Testons à présent nos certificats d'appareil avec des valeurs de température simulées ! Exécutez le script suivant qui (1) publie des nombres aléatoires sur le topic IoT de l'appareil, et (2) s'abonne à ce même topic pour afficher les valeurs reçues.
./pubsub_simulated_temps.py -c /home/pi/iot_certs/permanent_cert/perm_config.ini
Vous devriez obtenir une sortie similaire à celle-ci :

Félicitations, vous venez d'onboarder avec succès une petite flotte d'appareils IoT en suivant la méthodologie AWS conçue pour réaliser ce processus d'enregistrement de manière sécurisée et à grande échelle !
Pour tester vos connexions avec des données réelles, exécutez le script suivant. Il est similaire au précédent, à ceci près que (1) il ne s'abonne pas au topic sur lequel il publie, et (2) il envoie de vraies valeurs de température toutes les cinq secondes :
./publish_temps.py -c /home/pi/iot_certs/permanent_cert/perm_config.ini
La sortie devrait ressembler à ceci :

Si vous lancez ce script au démarrage via une tâche crontab (précédée d'un sleep de 30 s pour laisser aux modules onewire le temps de se charger au boot), votre appareil IoT reprendra son streaming en cas de redémarrage (in)attendu :
$ crontab -e
@reboot sleep 30 && /home/pi/publish_temps.py -c /home/pi/iot_certs/permanent_cert/perm_config.ini
Répétez les processus d'onboarding et de streaming pour tous les Raspberry Pi disposés dans votre maison. Vous voilà bien parti pour exploiter des données IoT à grande échelle !
La suite : stockage et visualisation
Rendez-vous dans la partie 2, où je traiterai du stockage et de la visualisation appropriés des données IoT streamées à grande échelle.
Mise en garde
L'approche pub/sub de publication de messages présentée ici convient surtout au cas d'usage de la télémétrie d'appareils, où les données streamées sont utilisées non seulement par une application analytique back-end, mais aussi directement par les utilisateurs finaux — par exemple via une application leur permettant de consulter les températures de leur domicile. Si les données streamées ne sont destinées qu'à une application back-end, il est plus économique de publier les messages via l'approche IoT Basic Ingest telle que définie dans le document AWS IoT Core Best Practices for Designing MQTT Topics. En publiant les messages sur un topic associé à une IoT Rule plutôt qu'à un topic IoT Core générique, vous perdez la possibilité de vous abonner au topic, mais en contrepartie, vous évitez de payer la composante messaging du tarif IoT.