Comment j'ai transformé mon bureau réglable en hauteur en bureau IoT

Dans cet article, je vais vous montrer comment j'ai transformé mon bureau à hauteur manuelle en un tableau IoT automatisé. Je vais expliquer comment dimensionner et faire fonctionner des moteurs, et comment connecter votre appareil IoT à Google en utilisant Heroku comme interface publique.



En bref, ce projet a deux caractéristiques. Premièrement, la table est connectée de Google Smart Home à Heroku à l'aide de commandes vocales, et deuxièmement: Heroku et la table elle-même communiquent en utilisant le protocole Internet des objets MQTT. MQTT est une bonne solution pour l'Internet des objets, ainsi que pour surmonter d'autres obstacles auxquels nous devrons faire face.



Tout d'abord, je dirai que j'ai fait ce projet juste pour le plaisir. J'espère que vous trouverez cet article amusant et vous motivera à prendre le temps de faire quelque chose de votre choix.



La même table




Partie matérielle



La première et probablement la partie la plus difficile du travail est la refonte de la table. Dans une vie antérieure, la table avait une poignée amovible, elle était située au bord du plateau. Au début, j'ai pensé à attacher quelque chose au trou de la poignée sans avoir à interférer avec le design de la table. J'ai acheté plusieurs disques pour comprendre comment fixer le moteur à la table, mais en vain. Puis l'idée est venue: une tige, courant sur toute la longueur de la table, qui relierait ses pieds de manière à ce qu'ils montent et descendent en même temps. Si j'attache un entraînement qui s'adapte à la tige, je peux utiliser une courroie pour connecter la tige au moteur. Il serait également possible d'équiper la table d'un moteur sans trop d'interférence avec sa conception.



L'importance du couple



Après avoir commandé le bon entraînement et la bonne courroie, j'ai commencé à chercher sur Amazon un moteur à couple élevé. Et - oh, miracle! - J'ai trouvé de nombreux moteurs adaptés! Du moins c'est ce qu'il m'a semblé ... Ayant acheté un petit moteur, j'ai attendu son arrivée de Chine pendant environ un mois. J'étais tellement excité quand le moteur est enfin arrivé! Je ne pouvais pas attendre le week-end pour enfin tout mettre en place et avoir mon bureau motorisé.



Les choses ne se sont pas déroulées comme prévu. J'ai passé la journée à percer un trou pour une tige dans les panneaux métalliques de la table. À ce moment-là, je n'avais que des outils à main, donc le processus a pris plus de temps que prévu. Vers la fin de la journée, j'ai fini d'assembler la table et j'étais prêt à l'essayer.



J'ai allumé le moteur, la tension sur l'alimentation de mon bureau et ... rien ne s'est passé. Quelques instants plus tard, le moteur a commencé à tourner et à grincer les dents de la courroie acquise. J'en ai tiré deux leçons: la courroie ne fait évidemment pas son travail, et le mot «moteur à couple élevé» ne signifie pas «je peux tout soulever». La deuxième leçon consiste à regarder la taille du moteur par rapport à vos doigts. Le mien s'est avéré minuscule!







Sur la gauche de la photo se trouvent un moteur et une courroie. En haut à droite se trouve un moteur attaché à la table (vous en verrez plus à ce sujet plus tard). En bas à droite, le moteur est en position sur la table.



Moteur approprié



Pour sélectionner le bon moteur, il était nécessaire de calculer le couple requis pour soulever le plateau. J'ai été surpris de voir à quel point il est facile de faire cela.







T=Fr







Le couple est la force multipliée par la longueur du bras de levier.



Eh bien, j'avais un bras de levier (c'est une poignée de table), il suffisait de calculer la force qui ferait facilement tourner le bras de levier. J'ai chargé la table en attachant le pot à lait à la poignée et j'ai graduellement ajouté de l'eau au pot jusqu'à ce que le levier se mette à tourner. En tournant la poignée vers le haut avec la cruche pleine, je me suis assuré que le poids tourne facilement la poignée. J'ai trouvé que le bras de levier mesure 11 cm de long et la force requise est de 4 lb. En remplaçant ces chiffres dans la formule, j'ai découvert que le moteur doit produire un couple d'au moins 19,95 kg / cm. Et j'ai commencé à le chercher.



J'ai décidé de refaire le tableau de manière irréversible. Je savais que la tige passant au milieu de la table était creuse. Après avoir recherché un moteur à double arbre, j'ai pu couper la tige et la remonter avec le moteur au milieu. En achetant deux moteurs avec un couple de 20 kg / cm, je me suis assuré qu'il y avait suffisamment de couple pour soulever la table.



Un autre beau samedi, j'ai démonté ma table en quatre morceaux, sciant les arbres du moteur afin qu'ils puissent être utilisés lors de l'assemblage de la tige. J'ai poussé plus de trous dans le métal pour s'adapter aux moteurs. Il n'y avait pas de courroie cette fois: les moteurs étaient connectés directement à la tige, les trous étaient assez grands. À la tombée de la nuit, j'ai remonté le bureau et l'ai chargé de fournitures de bureau.





Les deux photos du haut sont des moteurs entièrement montés sur la table. Les deux photos du bas sont une tige intégrée qui s'étend sur la longueur de la table à l'aide de moteurs.



J'ai branché les moteurs et les ai connectés à l'alimentation électrique. En allumant le courant, j'ai vu la table bouger! Cette fois, j'étais plus confiant, car j'avais correctement dimensionné les moteurs. J'ai doublé la puissance des moteurs certes, mais c'était incroyable de les voir bouger!



Cependant, permettez-moi de préciser que la table était lente. J'ai tourné une vidéo pour montrer à un ami comment fonctionne la table, mais il a dû activer l'accélération du temps sur la vidéo afin de ne pas regarder la table changer la position du dessus de la table pendant 5 minutes.



Le chiffre d'affaires est important. Version finale



J'ai finalement réalisé que tout se résumait à deux choses: le couple et les régimes. Il fallait trouver un moteur avec un nombre de tours suffisant à un couple déjà connu.



Ce n'était pas si difficile. Bien que je n’ai pas trouvé de moteur à double arbre, j’ai trouvé une boîte de vitesses rectangulaire qui convertit un moteur à arbre unique en un moteur à double arbre.



Bref, le mois suivant a été un mois d'attente pour une boîte de vitesses en provenance de Chine, et le samedi suivant après avoir attendu, j'avais une table qui tournait à la bonne vitesse.





Le dernier moteur lui-même est à gauche et le moteur installé est à droite. Peu de matériel et beaucoup de logiciels.



Je n'étais pas content de l'énorme alimentation électrique sur mon bureau, allongé juste pour contrôler la hauteur de la table. De plus, pour changer la position de la table de l'un à l'autre et inversement, j'ai permuté les fils. Petit problème, mais le projet a été fait pour idéalement simplement appuyer sur un bouton et avoir plusieurs préréglages de hauteur.



Bluetooth



La première solution était d'ajouter Bluetooth à la table. À la fin de la journée, il semble que presque tous les appareils de la maison disposent du Nluetooth, et le téléphone semble être une interface de contrôle pratique pour quelque chose comme mon bureau.



Alors maintenant, j'ai une carte contrôleur de moteur, une carte Bluetooth Nordic NRF52, des capteurs de distance et j'ai commencé à jouer avec le micrologiciel du contrôleur.



À la fin de l'article, je laisserai des liens vers les logiciels et micrologiciels que j'ai écrits pour le projet. N'hésitez pas à commenter le code: je ne suis pas un développeur de firmware professionnel et j'aimerais recevoir des conseils.



En guise d'introduction rapide: ESP32 est écrit en C ++ à l'aide de bibliothèques Arduino pour interagir avec l'application BLE Terminal sur le téléphone. L'installation et la configuration de BLE sont assez complexes. Tout d'abord, vous devez créer toutes les caractéristiques des valeurs que vous souhaitez contrôler via BLE. Considérez une caractéristique comme une variable dans votre code. BLE encapsule une variable dans plusieurs gestionnaires pour obtenir et définir la valeur de cette variable.



Les caractéristiques sont ensuite regroupées dans un service avec son propre UUID, ce qui rend le service unique et identifiable à partir de l'application. Enfin, vous devez ajouter ce service à la charge utile de l'annonce afin que votre service puisse être découvert par l'appareil. Lorsqu'un appareil distant se connecte à votre service et envoie des données via les spécifications, le tableau reconnaît que l'utilisateur souhaite régler la hauteur sur un autre préréglage et commence à se déplacer.



Pour le réglage en hauteur, le plan de travail est équipé d'un capteur LiDAR TFMini-S qui détecte la hauteur actuelle. C'est un capteur amusant: il s'appelle un LiDAR alors qu'il s'agit en fait d'un laser. Il utilise des optiques et des LED pour déterminer le temps de vol du rayonnement infrarouge. D'une manière ou d'une autre, le capteur détermine la hauteur de la table. Le tableau de commande détecte alors la différence entre l'altitude actuelle et l'altitude demandée et démarre le moteur qui tourne dans le sens souhaité. Certaines des parties principales du code sont présentées ci-dessous, mais vous pouvez voir le fichier entier ici .



void setup()
{
   Serial.begin(115200);
   Serial2.begin(TFMINIS_BAUDRATE);
   EEPROM.begin(3); // used for saving the height presets between reboots

   tfminis.begin(&Serial2);
   tfminis.setFrameRate(0);

   ledcSetup(UP_PWM_CHANNEL, PWM_FREQUENCY, PWM_RESOLUTION);
   ledcAttachPin(UP_PWM_PIN, UP_PWM_CHANNEL);

   ledcSetup(DOWN_PWM_CHANNEL, PWM_FREQUENCY, PWM_RESOLUTION);
   ledcAttachPin(DOWN_PWM_PIN, DOWN_PWM_CHANNEL);

   state_machine = new StateMachine();
   state_machine->begin(*t_desk_height, UP_PWM_CHANNEL, DOWN_PWM_CHANNEL);

   BLEDevice::init("ESP32_Desk");
  ...

   BLEServer *p_server = BLEDevice::createServer();
   BLEService *p_service = p_server->createService(BLEUUID(SERVICE_UUID), 20);

   /* ------------------- SET HEIGHT TO PRESET CHARACTERISTIC -------------------------------------- */
   BLECharacteristic *p_set_height_to_preset_characteristic = p_service->createCharacteristic(...);
   p_set_height_to_preset_characteristic->setCallbacks(new SetHeightToPresetCallbacks());
   /* ------------------- MOVE DESK UP CHARACTERISTIC ---------------------------------------------- */
   BLECharacteristic *p_move_desk_up_characteristic = p_service->createCharacteristic(...);
   p_move_desk_up_characteristic->setCallbacks(new MoveDeskUpCallbacks());
   /* ------------------- MOVE DESK UP CHARACTERISTIC ---------------------------------------------- */
   BLECharacteristic *p_move_desk_down_characteristic = p_service->createCharacteristic(...);
   p_move_desk_down_characteristic->setCallbacks(new MoveDeskDownCallbacks());
   /* ------------------- GET/SET HEIGHT 1 CHARACTERISTIC ------------------------------------------ */
   BLECharacteristic *p_get_height_1_characteristic = p_service->createCharacteristic(...);
   p_get_height_1_characteristic->setValue(state_machine->getHeightPreset1(), 1);
   BLECharacteristic *p_save_current_height_as_height_1_characteristic = p_service->createCharacteristic(...);
   p_save_current_height_as_height_1_characteristic->setCallbacks(new SaveCurrentHeightAsHeight1Callbacks());
   /* ------------------- GET/SET HEIGHT 2 CHARACTERISTIC ------------------------------------------ */
  ...
   /* ------------------- GET/SET HEIGHT 3 CHARACTERISTIC ------------------------------------------ */
  ...
   /* ------------------- END CHARACTERISTIC DEFINITIONS ------------------------------------------ */
   p_service->start();

   BLEAdvertising *p_advertising = p_server->getAdvertising();
   p_advertising->start();

   xTaskCreate(
       updateDeskHeight,     // Function that should be called
       "Update Desk Height", // Name of the task (for debugging)
       1024,                 // Stack size
       NULL,                 // Parameter to pass
       5,                    // Task priority
       NULL                  // Task handle
   );
}
      
      





Il y a beaucoup plus de choses dans le fichier, mais ce code a suffisamment de contexte pour comprendre ce qui se passe. Notez que nous créons et configurons tous les rappels BLE pour toutes les caractéristiques, y compris le mouvement manuel, le réglage et la récupération des valeurs prédéfinies, et surtout, l'alignement du tableau avec le préréglage.



L'image ci-dessous montre l'interaction avec les caractéristiques de réglage de la hauteur de la table. La dernière pièce du puzzle est une machine à états qui connaît la hauteur actuelle de la table, la hauteur souhaitée par l'utilisateur et fonctionne avec ces deux valeurs.



J'ai donc finalement eu une table qui faisait tout ce que je voulais. Je pourrais enregistrer la hauteur dans les préréglages et extraire les hauteurs de la mémoire pour régler la table sur mes positions préférées. J'ai utilisé le terminal BLEsur mon téléphone et mon ordinateur afin que je puisse envoyer des messages bruts à mon bureau et surveiller sa position. Cela a fonctionné, mais je savais que la bataille avec BLE ne faisait que commencer.





Interface bluetooth nue ... Il ne restait pour le moment qu'à apprendre à écrire des applications pour iOS ...



Après tout ça, ma femme a dit quelque chose qui a changé tout le projet: "Et si tu prenais le contrôle de ta voix?"



En plus d'être cool et d'ajouter un nouvel appareil à la liste de l'Assistant Google, il n'est pas nécessaire d'écrire une application iOS pour contrôler la table. Et vous n'avez plus besoin d'atteindre votre téléphone pour régler la hauteur. Encore une petite victoire!



Ajout de l'Internet des objets



Parlons maintenant de la mise à niveau de votre bureau vers la commande vocale via Google Smart Home et de la façon de le rendre compatible Wi-Fi.



L'ajout du Wi-Fi était assez simple. J'ai remplacé le microcontrôleur Nordic NRF52 par un ESP32 avec WiFi intégré. La plupart des logiciels étaient portables car ils étaient écrits en C ++, et les deux appareils pouvaient être programmés avec Platform.IO et les bibliothèques Arduino, y compris les tfmini-s que j'ai écrits pour mesurer la hauteur actuelle de la table.



L'architecture du système d'interaction de la table avec Google Smart Home est présentée ci-dessous. Parlons de l'interaction entre moi et Google.







Donc, Bluetooth a été activé. Il est temps de comprendre comment interagir avec Google Smart Home. Cette technologie contrôlait la maison à l'aide d' actions Smart Home . Ce qui est intéressant dans ses actions, c'est que le service agit comme un serveur OAuth2 et non comme un client. La plupart du travail effectué avec le serveur a consisté à implémenter une application OAuth2 Node.js Express qui accède à Heroku et communique comme un proxy entre Google et mon bureau.



J'ai eu de la chance: il y avait une implémentation de serveur décente utilisant deux bibliothèques. La première bibliothèque, node-oauth2-server, a été trouvée ici . La deuxième bibliothèque express-oauth-server pour la connexion Express a été trouvée ici .



const { Pool } = require("pg");
const crypto = require("crypto");
const pool = new Pool({
   connectionString: process.env.DATABASE_URL
});

module.exports.pool = pool;
module.exports.getAccessToken = (bearerToken) => {...};
module.exports.getClient = (clientId, clientSecret) => {...};
module.exports.getRefreshToken = (bearerToken) => {...};
module.exports.getUser = (email, password) => {...};
module.exports.getUserFromAccessToken = (token) => {...};
module.exports.getDevicesFromUserId = (userId) => {...};
module.exports.getDevicesByUserIdAndIds = (userId, deviceIds) => {...};
module.exports.setDeviceHeight = (userId, deviceId, newCurrentHeight) => {...};
module.exports.createUser = (email, password) => {...};
module.exports.saveToken = (token, client, user) => {...};
module.exports.saveAuthorizationCode = (code, client, user) => {...};
module.exports.getAuthorizationCode = (code) => {...};
module.exports.revokeAuthorizationCode = (code) => {...};
module.exports.revokeToken = (code) => {...};

      
      





Vient ensuite la configuration de l'application Express elle-même. Vous trouverez ci-dessous les points de terminaison requis pour un serveur OAuth, mais vous pouvez lire le fichier complet ici.



const express = require("express");
const OAuth2Server = require("express-oauth-server");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const flash = require("express-flash-2");
const session = require("express-session");
const pgSession = require("connect-pg-simple")(session);
const morgan = require("morgan");

const { google_actions_app } = require("./google_actions");
const model = require("./model");
const { getVariablesForAuthorization, getQueryStringForLogin } = require("./util");
const port = process.env.PORT || 3000;

// Create an Express application.
const app = express();
app.set("view engine", "pug");
app.use(morgan("dev"));

// Add OAuth server.
app.oauth = new OAuth2Server({
   model,
   debug: true,
});

// Add body parser.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static("public"));

// initialize cookie-parser to allow us access the cookies stored in the browser.
app.use(cookieParser(process.env.APP_KEY));

// initialize express-session to allow us track the logged-in user across sessions.
app.use(session({...}));

app.use(flash());

// This middleware will check if user's cookie is still saved in browser and user is not set, then automatically log the user out.
// This usually happens when you stop your express server after login, your cookie still remains saved in the browser.
app.use((req, res, next) => {...});

// Post token.
app.post("/oauth/token", app.oauth.token());

// Get authorization.
app.get("/oauth/authorize", (req, res, next) => {...}, app.oauth.authorize({...}));

// Post authorization.
app.post("/oauth/authorize", function (req, res) {...});
app.get("/log-in", (req, res) => {...});
app.post("/log-in", async (req, res) => {...});
app.get("/log-out", (req, res) => {...});
app.get("/sign-up", async (req, res) => {...});
app.post("/sign-up", async (req, res) => {...});
app.post("/gaction/fulfillment", app.oauth.authenticate(), google_actions_app);
app.get('/healthz', ((req, res) => {...}));
app.listen(port, () => {
   console.log(`Example app listening at port ${port}`);
});
      
      





Il y a beaucoup de code, mais je vais vous expliquer les principaux points. Les deux routes OAuth2 utilisées pour le serveur sont / oauth / token et / oauth / authorize. Ils sont utilisés pour recevoir un nouveau jeton ou actualiser les jetons expirés. Ensuite, vous devez faire en sorte que le serveur réponde à l'action de Google. Vous remarquerez que le point de terminaison / gaction / accomplissement pointe vers un objet google_actions_app



.



Google envoie des demandes à votre serveur dans un format spécifique et fournit une bibliothèque pour aider à traiter ces demandes. Vous trouverez ci-dessous les fonctions nécessaires pour communiquer avec Google, et le fichier complet est ici. Enfin, il y a le point de terminaison / healthz, que je couvrirai à la fin de l'article.



Le point de terminaison / gaction / réalisation utilise un middleware appelé app.oauth.authenticate (), le dur travail de mise en service du serveur OAuth2 consistait à faire fonctionner ce middleware. Il vérifie que le jeton porteur qui nous est fourni par Google fait référence à un utilisateur existant et n'a pas expiré. La route envoie ensuite la demande et la réponse à l'objet google_actions_app



.



Google envoie des demandes à votre serveur dans un format spécifique et fournit une bibliothèque pour vous aider à analyser et à traiter ces demandes. Vous trouverez ci-dessous les fonctionnalités dont vous avez besoin pour contacter Google, mais vous pouvez afficher l'intégralité du fichier ici .



const { smarthome } = require('actions-on-google');
const mqtt = require('mqtt');
const mqtt_client = mqtt.connect(process.env.CLOUDMQTT_URL);

const model = require('./model');
const { getTokenFromHeader } = require('./util');

mqtt_client.on('connect', () => {
   console.log('Connected to mqtt');
});

const updateHeight = {
   "preset one": (deviceId) => {
       mqtt_client.publish(`/esp32_iot_desk/${deviceId}/command`, "1");
   },
   "preset two": (deviceId) => {
       mqtt_client.publish(`/esp32_iot_desk/${deviceId}/command`, "2");
   },
   "preset three": (deviceId) => {
       mqtt_client.publish(`/esp32_iot_desk/${deviceId}/command`, "3");
   },
};

const google_actions_app = smarthome({...});
google_actions_app.onSync(async (body, headers) => {...});
google_actions_app.onQuery(async (body, headers) => {...});
google_actions_app.onExecute(async (body, headers) => {...});
module.exports = { google_actions_app };
      
      





Lorsque vous ajoutez une action intelligente à votre compte Google, Google effectuera une demande de synchronisation. Cette requête vous permet de savoir quels appareils sont disponibles à partir de votre compte. Vient ensuite une requête d'interrogation: Google interroge vos appareils pour déterminer leur état actuel.



Lorsque vous ajoutez pour la première fois une action Google à votre compte Smart Home, vous remarquerez que Google envoie d'abord une demande de synchronisation, puis une demande d'interrogation pour obtenir une vue holistique de vos appareils. La dernière est une demande est une demande de satisfaction que Google demande à vos appareils de faire quelque chose.



«Caractéristiques» (trait) de l'appareil Google Smart Home



Google utilise des fonctionnalités spécifiques aux appareils pour fournir des éléments d'interface utilisateur permettant de contrôler vos appareils à Google et pour créer des modèles de communication de commande vocale. Certaines des fonctionnalités incluent les paramètres suivants: ColorSetting, Modes, OnOff et StartStop. Il m'a fallu un certain temps pour décider quelle fonctionnalité fonctionnerait le mieux dans mon application, mais plus tard, j'ai choisi les modes.



Vous pouvez considérer les modes comme une liste déroulante où l'une des N valeurs prédéfinies est sélectionnée ou, dans mon cas, une hauteur prédéfinie. J'ai nommé mon mode "hauteur" et les valeurs possibles sont "preset one", "preset two" et "preset three". Cela me permet de contrôler mon bureau en disant: "Ok Google, règle la hauteur de mon bureau sur une hauteur prédéfinie" et Google enverra une demande d'exécution correspondante à mon système. Vous pouvez en savoir plus sur les fonctionnalités des appareils Google ici .



Projet en action



Enfin, Google Smart Home et mon ordinateur ont commencé à communiquer. Avant cela, j'utilisais ngrok pour exécuter le serveur Express localement . Maintenant que mon serveur fonctionne enfin assez bien, il est temps de le mettre à disposition de Google à tout moment. Il était donc nécessaire d'héberger l'application sur Heroku - c'est un fournisseur PaaS qui facilite le déploiement et la gestion des applications.



L'un des principaux avantages d'Heroku est le mode add-on. Avec les modules complémentaires, il est très facile d'ajouter des serveurs CloudMQTT et Postgres à votre application. Un autre avantage de l'utilisation d'Heroku est sa facilité d'assemblage et de déploiement. Heroku détecte automatiquement le code que vous utilisez et le construit / le déploie pour vous. Vous pouvez trouver plus de détails à ce sujet en lisant sur Heroku Buildpacks . Dans mon cas, chaque fois que je pousse du code vers git remote Heroku, il installe tous mes packages, supprime toutes les dépendances de développement et déploie l'application, le tout avec une simple commande "git push heroku main".



En quelques clics, CloudMQTT et Postgres étaient disponibles pour mon application, et je n'avais besoin que de quelques variables d'environnement pour intégrer ces services à mon application. Heroku n'a pas demandé d'argent. Cependant, CloudMQTT est un module complémentaire tiers pour 5 $ par mois.



Je pense que le besoin de Postgres est explicite, mais CloudMQTT mérite plus d'attention.



De l'Internet à un réseau privé. À la dure



Il existe plusieurs façons de donner accès à une application ou, dans mon cas, à un appareil IoT. La première consiste à ouvrir un port sur mon réseau domestique pour amener l'appareil sur Internet. Dans ce cas, mon application Heroku Express enverra une demande à mon appareil en utilisant l'adresse IP publique. Cela m'obligerait à avoir une adresse IP statique publique ainsi qu'une adresse IP statique pour l'ESP32. ESP32 devrait également agir comme un serveur HTTP et écouter les instructions d'Heroku tout le temps. C'est une surcharge importante pour un appareil qui reçoit des instructions plusieurs fois par jour.



La deuxième méthode s'appelle une perforatrice. Avec lui, vous pouvez utiliser un serveur externe tiers pour accéder à l'appareil à Internet sans avoir besoin de redirection de port. Votre appareil se connecte essentiellement à un serveur qui configure un port ouvert. Ensuite, un autre service peut se connecter directement à votre appareil interne en obtenant un port ouvert à partir du serveur externe. Enfin, il se connecte directement à l'appareil en utilisant ce port ouvert. L'approche peut ou peut ne pas être tout à fait correcte: je n'ai lu qu'une partie de l'article à ce sujet.



Il se passe beaucoup de choses à l’intérieur de la perforatrice et je ne comprends pas tout à fait ce qui se passe. Cependant, si vous êtes curieux, il existe des articles intéressants pour en expliquer davantage. Voici deux articles que j'ai lus pour mieux comprendre la perforation: Wikipediaet un article du MIT par Brian Ford et d'autres .



De l'Internet à un réseau privé via l'IoT



Je n'étais pas très content de ces solutions. J'ai connecté beaucoup d'appareils intelligents à ma maison et je n'ai jamais eu à ouvrir un port sur mon routeur, il n'y avait donc pas de redirection de port. De plus, percer des trous semble beaucoup plus difficile que ce que je recherche et est mieux adapté aux réseaux P2P. À la suite de recherches supplémentaires, j'ai découvert MQTT et appris qu'il s'agissait d'un protocole pour l'IoT. Il présente certains avantages tels qu'une faible consommation d'énergie, une tolérance de panne configurable et ne nécessite pas de redirection de port. MQTT est un protocole éditeur / abonné, ce qui signifie qu'une table est un abonné à un sujet spécifique et qu'une application Heroku est l'éditeur de ce sujet.



Alors Google contacte Heroku, cette demande est analysée pour déterminer l'appareil demandé et son nouvel état ou mode. L'application Heroku publie ensuite un message sur le serveur CloudMQTT déployé en tant que module complémentaire à Heroku demandant à la table d'accéder au nouveau préréglage. Enfin, le tableau s'abonne au sujet et reçoit un message posté par l'application Heroku, enfin, le tableau ajuste sa hauteur comme demandé! Dans le fichier googleactionsapp, vous remarquerez qu'il existe une fonction updateHeight qui publie un numéro MQTT pour un ID d'appareil spécifique. C'est ainsi que l'application Heroku publie une demande de déplacement de table vers MQTT.



La dernière étape consiste à recevoir le message sur l'ESP32 et à déplacer la table. Je vais vous montrer quelques-uns des points forts du code de la table ci-dessous, et tout le code source est ici .



void setup()
{
 Serial.begin(115200);
...
 tfminis.begin(&Serial2);
 tfminis.setFrameRate(0);

...

 state_machine = new StateMachine();
 state_machine->begin(*t_desk_height, UP_PWM_CHANNEL, DOWN_PWM_CHANNEL);

 setup_wifi();

 client.setServer(MQTT_SERVER_DOMAIN, MQTT_SERVER_PORT);
 client.setCallback(callback);
...
}
      
      





Lorsque la table est chargée, nous initions d'abord la communication entre le TFMini-S - le capteur de distance - pour obtenir la hauteur actuelle de la table. Ensuite, nous mettons en place la machine d'état pour le mouvement de table. La machine d'état reçoit des commandes via MQTT et est alors responsable de faire correspondre la demande de l'utilisateur à la hauteur de table réelle telle que lue par le capteur de distance. Enfin, nous nous connectons au réseau Wi-Fi, nous nous connectons au serveur MQTT et nous configurons un rappel pour toutes les données reçues sur le sujet MQTT auquel nous sommes abonnés. Ci-dessous, je vais montrer la fonction de rappel.



void callback(char *topic, byte *message, unsigned int length)
{
 ...

 String messageTemp;

 for (int i = 0; i < length; i++)
 {
   messageTemp += (char)message[i];
 }

 if (messageTemp == "1") {
   state_machine->requestStateChange(ADJUST_TO_PRESET_1_HEIGHT_STATE);
 }

 if (messageTemp == "2") {
   state_machine->requestStateChange(ADJUST_TO_PRESET_2_HEIGHT_STATE);
 }

 if (messageTemp == "3") {
   state_machine->requestStateChange(ADJUST_TO_PRESET_3_HEIGHT_STATE);
 }
...
}
      
      





La machine à états enregistre le changement d'état reçu dans la rubrique MQTT. Ensuite, il traite le nouvel état dans la boucle principale.



void loop()
{
 if (!client.connected())
 {
   reconnect();
 }
 client.loop();
 state_machine->processCurrentState();
}
      
      





La boucle principale fait plusieurs choses: d'abord, elle se reconnecte au serveur MQTT si elle n'est pas déjà connectée. Ensuite, il traite toutes les données reçues via la rubrique MQTT. Enfin, le code fonctionne en déplaçant la table vers l'emplacement souhaité demandé dans la rubrique MQTT.



C'est tout! La table est entièrement contrôlée par la voix et communique avec Google pour recevoir des commandes!



Notes récentes



Le dernier point de terminaison que je n'ai pas mentionné est le point de terminaison / healthz. Cela est dû au fait que Google attend une réponse assez rapide et que le chargement de l'application Heroku à chaque demande ne fonctionne pas dans mon cas. J'ai mis en place un service de ping pour cingler le point de terminaison / healthz toutes les minutes pour maintenir le service sain et prêt à répondre. Si vous prévoyez de faire quelque chose comme ça, rappelez-vous que toutes les heures gratuites au stand seront consacrées à cela. Tout va bien maintenant: c'est la seule application utilisée sur Heroku. De plus, pour 7 $ par mois, vous pouvez passer au plan Heroku's Hobby qui permet à l'application de continuer à fonctionner.



La construction d'un appareil IoT entraîne de nombreux frais généraux au début. J'ai conçu le matériel, construit le schéma de contrôle, configuré le serveur MQTT, écrit le serveur Express OAuth2 et appris à interagir avec Google Smart Home via des actions. Les frais généraux initiaux étaient énormes, mais j'ai l'impression d'avoir accompli beaucoup de choses! Sans oublier, MQTT Server, Express OAuth2 Application Server et Google Smart Home Actions peuvent être utilisés pour un autre projet. Je suis intéressé par les maisons intelligentes et je peux essayer d'élargir mon répertoire d'appareils IoT pour inclure des capteurs qui suivent ce qui se passe autour de ma maison et le signalent via MQTT. Les capteurs de surveillance du sol, de température et de lumière seront très intéressants à surveiller et à analyser.



Et après?



Les hauteurs de comptoir sont désormais mesurées de manière non fiable au mieux. J'utilise en général un capteur de distance infrarouge fonctionnel TFMini-S. On a remarqué que la hauteur de la table change légèrement pendant la journée lorsque l'éclairage ambiant de la pièce change. J'ai commandé un capteur d'angle de rotation pour calculer les révolutions d'une tige à travers la table. Cela devrait me donner un mouvement plus précis à tout moment de la journée. J'ai également accès au serveur que j'héberge au sous-sol. Là-dessus, je peux explorer mon propre serveur Mosquitto MQTT, les applications Node-RED et OAuth2 Express si je veux héberger quelque chose moi-même. Enfin, maintenant tous les appareils électroniques sont sur mon bureau. Je prévois d'organiser les appareils pour que tout soit beau et net!



Merci d'avoir lu l'article! Pour plus de commodité, je donne tous les liens.




image









All Articles