


Comment construire un tableau de bord Wi-Fi à l'aide de Node.js et Racactive.js
Les plats clés
- Utilisez Node.js pour créer un serveur qui étend les fonctionnalités existantes pour inclure des informations réseau Wi-Fi, ce qui rend le tableau de bord plus complet.
- Implémentez Racactive.js pour que le côté client gére plus efficacement les mises à jour et les interactions en temps réel, améliorant l'expérience utilisateur avec les mises à jour de contenu dynamique.
- Traiter les sorties de commande Wi-Fi sur le serveur pour extraire et afficher les détails du réseau disponibles, garantir que les données sont structurées et prêtes à utiliser le client.
- Concevoir et utiliser des modèles HTML avec Racactive.js pour afficher les données du réseau Wi-Fi, permettant des éléments Web interactifs et réactifs qui améliorent la navigation et la convivialité.
- élargir les capacités du tableau de bord en ajoutant de nouveaux points de terminaison et en manipulant efficacement les appels AJAX, garantissant que le tableau de bord reste évolutif et maintenable.

serveur
Du côté du serveur, nous allons réutiliser et étendre ce que nous avons créé pour la batterie à savoir. Dans ce didacticiel, nous nous concentrerons sur Ubuntu, mais le code du serveur est structuré de manière à ce que vous deviez écrire quelques adaptateurs pour prendre en charge les machines Mac ou Windows.BASH COMMAND
Pour commencer, nous étendons la méthode de configuration d'origine en ajoutant des commandes et des rappels pour le nouveau point de terminaison. Un renommage a été nécessaire pour empêcher les affrontements avec les commandes du widget de la batterie.<span>function switchConfigForCurrentOS () { </span> <span>switch(process.platform) { </span> <span>case 'linux': </span> <span>return { </span> <span>batteryCommand: 'upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep -E "state|time to empty|to full|percentage"', </span> <span>batteryProcessFunction: processBatteryStdoutForLinux, </span> <span>wifiCommand: 'iwlist wlan0 scanning | egrep "Cell |Address|Channel|Frequency|Encryption|Quality|Signal level|Last beacon|Mode|Group Cipher|Pairwise Ciphers|Authentication Suites|ESSID"', </span> <span>wifiProcessFunction: processWifiStdoutForLinux </span> <span>}; </span> <span>case 'darwin': //MAc OsX </span> <span>... </span> <span>} </span> <span>}</span>
Traiter la sortie de la commande
La façon dont nous traitons la sortie de commande est vraiment similaire à ce que nous avons déjà fait pour la batterie. Nous passons par la sortie ligne par ligne et le traitons pour extraire des paramètres significatifs de nos lectures. Mais dans ce cas, nous obtenons des lectures sur une liste d'articles, pas un seul! Nous devons donc identifier quand un nouvel élément démarre réellement dans la sortie et créer un nouvel objet pour chaque élément. Ensuite, nous filtrerons les lignes valides, en ajoutant les propriétés que nous lisons à notre élément actuel.<span>function processWifiStdoutForLinux(stdout) { </span> <span>var networks = {}; </span> <span>var net_cell = ""; </span> <span>var cell = {}; </span> stdout<span>.split('\n').map(trimParam).forEach(function (line) { </span> <span>if (line.length > 0) { </span> <span>//check if the line starts a new cell </span> <span>if (stringStartsWith(line, NET_CELL_PREFIX)) { </span> <span>if (net_cell.length > 0) { </span> networks<span>[net_cell] = mapWifiKeysForLinux(cell); </span> <span>} </span> cell <span>= {}; </span> line <span>= line.split("-"); </span> net_cell <span>= line[0].trim(); </span> line <span>= line[1]; </span> <span>} </span> <span>//Either way, now we are sure we have a non empty line with (at least one) key-value pair </span> <span>// and that cell has been properly initialized </span> <span>processWifiLineForLinux(cell, line); </span> <span>} </span> <span>}); </span> <span>if (net_cell.length > 0) { </span> networks<span>[net_cell] = mapWifiKeysForLinux(cell); </span> <span>} </span> <span>return networks; </span> <span>}</span>
- Puisque nous ajoutons une cellule à notre hachage uniquement lorsque la description de la suivante commence, nous manquerions autrement l'instruction finale IF (pour capturer le dernier réseau de la sortie).
- Le code ci-dessus suppose que deux cellules ne peuvent pas partager le même nom. Il s'agit d'une hypothèse raisonnable car les réseaux ne sont pas indexés par leur nom (cette information est capturée par le champ Essid). Ils sont répertoriés et attribués un identifiant progressif "Cell 0x" .
- La dernière chose que nous faisons avant de stocker les propriétés est un appel à mapwifikeysforlinux et dans ce cas, ils retournent les clés inchangées.
<span>function switchConfigForCurrentOS () { </span> <span>switch(process.platform) { </span> <span>case 'linux': </span> <span>return { </span> <span>batteryCommand: 'upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep -E "state|time to empty|to full|percentage"', </span> <span>batteryProcessFunction: processBatteryStdoutForLinux, </span> <span>wifiCommand: 'iwlist wlan0 scanning | egrep "Cell |Address|Channel|Frequency|Encryption|Quality|Signal level|Last beacon|Mode|Group Cipher|Pairwise Ciphers|Authentication Suites|ESSID"', </span> <span>wifiProcessFunction: processWifiStdoutForLinux </span> <span>}; </span> <span>case 'darwin': //MAc OsX </span> <span>... </span> <span>} </span> <span>}</span>
Point de terminaison
L'ajout du nouveau point de terminaison à notre serveur est trivial grâce au module HHTP de Node et aux méthodes d'aide que nous avons créées dans le tutoriel précédent. Nous avons juste besoin de définir l'expression régulière des chemins auxquels nous voulons répondre et d'ajouter une instruction IF au rappel du serveur, déclenché sur les demandes entrantes:<span>function processWifiStdoutForLinux(stdout) { </span> <span>var networks = {}; </span> <span>var net_cell = ""; </span> <span>var cell = {}; </span> stdout<span>.split('\n').map(trimParam).forEach(function (line) { </span> <span>if (line.length > 0) { </span> <span>//check if the line starts a new cell </span> <span>if (stringStartsWith(line, NET_CELL_PREFIX)) { </span> <span>if (net_cell.length > 0) { </span> networks<span>[net_cell] = mapWifiKeysForLinux(cell); </span> <span>} </span> cell <span>= {}; </span> line <span>= line.split("-"); </span> net_cell <span>= line[0].trim(); </span> line <span>= line[1]; </span> <span>} </span> <span>//Either way, now we are sure we have a non empty line with (at least one) key-value pair </span> <span>// and that cell has been properly initialized </span> <span>processWifiLineForLinux(cell, line); </span> <span>} </span> <span>}); </span> <span>if (net_cell.length > 0) { </span> networks<span>[net_cell] = mapWifiKeysForLinux(cell); </span> <span>} </span> <span>return networks; </span> <span>}</span>
<span>function processWifiLineForLinux(cell<span>, line</span>) { </span> <span>var key; </span> <span>var val; </span> line <span>= line.trim(); </span> <span>if (line.length > 0) { </span> <span>switch (true) { </span> <span>case stringStartsWith(line, NET_ADDRESS_PREFIX): </span> line <span>= line.split(':'); </span> line<span>.splice(0, 1); </span> <span>//INVARIANT: Address in the format Address: DC:0B:1A:47:BA:07 </span> <span>if (line.length > 0) { </span> cell<span>[NET_ADDRESS_PREFIX] = line.join(":"); </span> <span>} </span> <span>break; </span> <span>case stringStartsWith(line, NET_QUALITY_PREFIX): </span> <span>//INVARIANT: this line must have a similar format: Quality=41/70 Signal level=-69 dBm </span> line <span>= line.split(NET_SIGNAL_PREFIX); </span> cell<span>[NET_QUALITY_PREFIX] = line[0].split("=")[1].trim(); </span> <span>if (line.length > 1) { </span> cell<span>[NET_SIGNAL_PREFIX] = line[1].split("=")[1].trim(); </span> <span>} </span> <span>break; </span> <span>case stringStartsWith(line, NET_EXTRA_PREFIX): </span> <span>//INVARIANT: this line must have a similar format: Extra: Last beacon: 1020ms ago </span> line <span>= line.split(":"); </span> <span>//we can ignore the prefix of the string </span> <span>if (line.length > 2) { </span> cell<span>[line[1].trim()] = line[2].trim(); </span> <span>} </span> <span>break; </span> <span>default: </span> <span>//INVARIANT: the field must be formatted as "key : value" </span> line <span>= line.split(":"); </span> <span>if (line.length > 1) { </span> <span>//Just stores the key-value association, so that coupling with client is reduced to the min: </span> <span>//values will be examined only on the client side </span> cell<span>[line[0].trim()] = line[1].trim(); </span> <span>} </span> <span>} </span> <span>} </span> <span>return cell; </span> <span>}</span>
Client
Maintenant, permettez-moi de vous présenter la partie la plus drôle de cet exemple. Nous allons utiliser massivement Racactive.js pour le client Web. Il s'agit d'un framework léger et puissant qui combine la reliure bidirectionnelle (style AngularJS) avec des modèles HTML (comme la moustache ou guidon). Le stress sur les modèles (encore plus qu'AngularJS, bien plus que réagir), est en effet l'une des caractéristiques de Racactive.js, ainsi que ses performances peu rapides, en raison d'un moteur intelligent qui calcule toujours les plus petits éléments DOM possible actualisé lorsque les données changent. Nous allons ajouter deux panneaux à notre tableau de bord:- un pour la liste des réseaux dans notre environnement (montrant un bref résumé pour chaque élément).
- Un autre qui n'apparaît qu'une fois un réseau sélectionné et affiche des informations détaillées pour cette connexion Wi-Fi.
Modèle
Commençons par discuter des modèles HTML pour afficher nos données, puis nous verrons comment leur lier les données du serveur.Liste Wi-Fi
Le modèle le plus complexe dont nous avons besoin est celui qui affiche la liste des réseaux disponibles. La première douzaine de lignes définissent simplement le panneau de conteneur et utilisez la liaison de Racactive.js pour afficher conditionnellement un avertissement d'icône concernant les erreurs de serveur, et un bouton pour interrompre / reprendre le sondage du serveur:<span>var server = http.createServer(function (request<span>, response</span>) { </span> <span>var requestUrl = request.url; </span> <span>var filePath = BASE_URL + requestUrl; </span> <span>if (requestUrl === '/' || requestUrl === '') { </span> response<span>.writeHead(301, </span> <span>{ </span> <span>Location: BASE_URL + 'public/demo.html' </span> <span>}); </span> response<span>.end(); </span> <span>} else if (RE_BATTERY.test(requestUrl)) { </span> <span>getBatteryStatus(response, onBatteryInfo, onError); </span> <span>} else if (RE_NETWORKS.test(requestUrl)) { </span> <span>getWifiStatus(response, onWifiInfo, onError); </span> <span>} </span> <span>... </span> <span>}</span>
La deuxième partie du modèle est beaucoup plus intéressante. Nous itérons dans la liste des réseaux avec {{#WiFinetWorks: num}}, Capturant l'index de chaque élément dans la variable NUM. Pour chaque élément de la liste, nous ajoutons un clic de gestion de rappel (voir ci-dessous) et affichons un résumé de ses valeurs. Remarquez comment les balises de clôture n'ont pas à faire correspondre le texte des balises d'ouverture:
<span>function switchConfigForCurrentOS () { </span> <span>switch(process.platform) { </span> <span>case 'linux': </span> <span>return { </span> <span>batteryCommand: 'upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep -E "state|time to empty|to full|percentage"', </span> <span>batteryProcessFunction: processBatteryStdoutForLinux, </span> <span>wifiCommand: 'iwlist wlan0 scanning | egrep "Cell |Address|Channel|Frequency|Encryption|Quality|Signal level|Last beacon|Mode|Group Cipher|Pairwise Ciphers|Authentication Suites|ESSID"', </span> <span>wifiProcessFunction: processWifiStdoutForLinux </span> <span>}; </span> <span>case 'darwin': //MAc OsX </span> <span>... </span> <span>} </span> <span>}</span>
Détails Wi-Fi sélectionnés
<span>function processWifiStdoutForLinux(stdout) { </span> <span>var networks = {}; </span> <span>var net_cell = ""; </span> <span>var cell = {}; </span> stdout<span>.split('\n').map(trimParam).forEach(function (line) { </span> <span>if (line.length > 0) { </span> <span>//check if the line starts a new cell </span> <span>if (stringStartsWith(line, NET_CELL_PREFIX)) { </span> <span>if (net_cell.length > 0) { </span> networks<span>[net_cell] = mapWifiKeysForLinux(cell); </span> <span>} </span> cell <span>= {}; </span> line <span>= line.split("-"); </span> net_cell <span>= line[0].trim(); </span> line <span>= line[1]; </span> <span>} </span> <span>//Either way, now we are sure we have a non empty line with (at least one) key-value pair </span> <span>// and that cell has been properly initialized </span> <span>processWifiLineForLinux(cell, line); </span> <span>} </span> <span>}); </span> <span>if (net_cell.length > 0) { </span> networks<span>[net_cell] = mapWifiKeysForLinux(cell); </span> <span>} </span> <span>return networks; </span> <span>}</span>
javascript
Nous allons configurer un démon de sondage qui interroge de manière asynchrone le serveur à des intervalles de temps donnés. Chaque appel Ajax fournira la liste mise à jour des réseaux Wi-Fi. Tout ce que nous avons à faire lorsque nous recevons une réponse JSON du serveur, c'est de reconnaître que nous avons reçu une réponse réussie et mis à jour les champs dans lesquels nous stockons la liste des réseaux à l'intérieur de l'objet RACTIVE.Configuration
Comme nous l'avons montré dans l'article précédent, pour lier un modèle à certaines données, nous avons juste besoin de créer un nouvel objet rage, de le connecter avec l'ID du modèle (#MeterVizTemplate ci-dessous), et les éléments DOM cible, c'est-à-dire le nœud Ce sera le parent du modèle dans l'arbre Dom (panneaux ci-dessous). Ensuite, nous avons juste besoin d'ajouter tous les objets ou valeurs que nous voulons utiliser dans le modèle comme champs de racactive.data. Cela peut être fait sur l'initialisation (comme ci-dessous) ou ultérieure, en utilisant Racactive.Set ().<span>function processWifiLineForLinux(cell<span>, line</span>) { </span> <span>var key; </span> <span>var val; </span> line <span>= line.trim(); </span> <span>if (line.length > 0) { </span> <span>switch (true) { </span> <span>case stringStartsWith(line, NET_ADDRESS_PREFIX): </span> line <span>= line.split(':'); </span> line<span>.splice(0, 1); </span> <span>//INVARIANT: Address in the format Address: DC:0B:1A:47:BA:07 </span> <span>if (line.length > 0) { </span> cell<span>[NET_ADDRESS_PREFIX] = line.join(":"); </span> <span>} </span> <span>break; </span> <span>case stringStartsWith(line, NET_QUALITY_PREFIX): </span> <span>//INVARIANT: this line must have a similar format: Quality=41/70 Signal level=-69 dBm </span> line <span>= line.split(NET_SIGNAL_PREFIX); </span> cell<span>[NET_QUALITY_PREFIX] = line[0].split("=")[1].trim(); </span> <span>if (line.length > 1) { </span> cell<span>[NET_SIGNAL_PREFIX] = line[1].split("=")[1].trim(); </span> <span>} </span> <span>break; </span> <span>case stringStartsWith(line, NET_EXTRA_PREFIX): </span> <span>//INVARIANT: this line must have a similar format: Extra: Last beacon: 1020ms ago </span> line <span>= line.split(":"); </span> <span>//we can ignore the prefix of the string </span> <span>if (line.length > 2) { </span> cell<span>[line[1].trim()] = line[2].trim(); </span> <span>} </span> <span>break; </span> <span>default: </span> <span>//INVARIANT: the field must be formatted as "key : value" </span> line <span>= line.split(":"); </span> <span>if (line.length > 1) { </span> <span>//Just stores the key-value association, so that coupling with client is reduced to the min: </span> <span>//values will be examined only on the client side </span> cell<span>[line[0].trim()] = line[1].trim(); </span> <span>} </span> <span>} </span> <span>} </span> <span>return cell; </span> <span>}</span>
Daemons
Nous utiliserons le même mécanisme pour le démon et pour faire une pause / redémarrer le serveur que nous l'avons fait pour la batterie. Par souci de concision, nous ne le répéterons pas ici, mais si vous souhaitez approfondir ce sujet, vous pouvez jeter un œil à cet article ou au référentiel GitHub.Ajax appelle
La seule chose que fait notre nouveau démon, c'est de passer un appel AJAX, puis de mettre à jour nos données en cas de succès ou des problèmes de réseau de signalisation sur le terrain, en cas d'erreurs.<span>var server = http.createServer(function (request<span>, response</span>) { </span> <span>var requestUrl = request.url; </span> <span>var filePath = BASE_URL + requestUrl; </span> <span>if (requestUrl === '/' || requestUrl === '') { </span> response<span>.writeHead(301, </span> <span>{ </span> <span>Location: BASE_URL + 'public/demo.html' </span> <span>}); </span> response<span>.end(); </span> <span>} else if (RE_BATTERY.test(requestUrl)) { </span> <span>getBatteryStatus(response, onBatteryInfo, onError); </span> <span>} else if (RE_NETWORKS.test(requestUrl)) { </span> <span>getWifiStatus(response, onWifiInfo, onError); </span> <span>} </span> <span>... </span> <span>}</span>
2. Vous pouvez faire confiance au serveur que vous appelez. Étant donné que nous n'utilisons pas de contenu fourni par l'utilisateur pour l'URL, on pourrait penser que cela ne devrait pas être une préoccupation. Cependant, si notre serveur devait être compromis, nous n'aurions aucune barrière pour nous protéger contre le code injecté. Si un en-tête «DataType» explicite n'est pas défini, JQuery essaiera de deviner le contenu de la réponse, et une réponse d'un serveur malveillant peut contenir du code JavaScript. Bien que cette possibilité ne soit pas si courante, nous ne pouvons pas l'exclure complètement. Pour cette raison, ce n'est pas une mauvaise idée ajoutant une couche supplémentaire de protection au prix d'un peu plus de frappe.
Mise à jour du tableau de bord
Le module complémentaire le plus pertinent pour cette étape sera que nous répondons aux clics sur la liste et que nous affichons les détails du réseau sélectionné:<span>function switchConfigForCurrentOS () { </span> <span>switch(process.platform) { </span> <span>case 'linux': </span> <span>return { </span> <span>batteryCommand: 'upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep -E "state|time to empty|to full|percentage"', </span> <span>batteryProcessFunction: processBatteryStdoutForLinux, </span> <span>wifiCommand: 'iwlist wlan0 scanning | egrep "Cell |Address|Channel|Frequency|Encryption|Quality|Signal level|Last beacon|Mode|Group Cipher|Pairwise Ciphers|Authentication Suites|ESSID"', </span> <span>wifiProcessFunction: processWifiStdoutForLinux </span> <span>}; </span> <span>case 'darwin': //MAc OsX </span> <span>... </span> <span>} </span> <span>}</span>
- Appelez une méthode qui prendrait l'ID du réseau sélectionné;
- l'utiliser pour trouver l'objet réseau pour cet ID (probablement stocké dans un dictionnaire);
- Trouvez l'élément DOM pour le «Panneau réseau sélectionné»;
- Retirez l'ancien arbre Dom à l'intérieur du panneau et créez une nouvelle liste affichant les associations de valeurs clés, en mélangeant de nombreuses chaînes HTML à l'intérieur de notre code JavaScript.
Conclusions
Fini! Nous avons notre tableau de bord «pimpé». Comme je l'ai dit dans l'introduction, ce n'est qu'un point de départ.Si vous avez suivi, vous devriez maintenant être en mesure d'afficher facilement des listes d'éléments complexes, de gérer la sélection des éléments et de communiquer en toute sécurité au serveur. Vous pouvez utiliser ces compétences pour un certain nombre d'autres tâches, pas nécessairement impliquant des statistiques pour votre ordinateur portable. De montrer une liste de restaurants autour de l'utilisateur à l'énumération des appareils électroménagers, vous pouvez contrôler tout au long d'une interface Web ou de votre mobile. Le choix vous appartient et il n'y a pas de limite. Si vous souhaitez approfondir les sujets abordés dans cet article, je vous suggère de jeter un œil à ces bonnes ressources:
- Création d'une batterie à savoir en utilisant Node.js: démarrage et serveur
- Tutoriel interactif sur racactive.js
- jQuery $ .getjson Méthode
- Discussion sur stackOverflow sur jQuery.get () Méthode
Questions fréquemment posées (FAQ) sur la construction d'un tableau de bord Wi-Fi
Quelles sont les conditions préalables à la construction d'un tableau de bord Wi-Fi?
Pour construire un tableau de bord Wi-Fi, vous devez avoir une compréhension de base de JavaScript et Node.js. Vous devez également que Node.js et NPM (Node Package Manager) soient installés sur votre ordinateur. Si vous ne les avez pas installés, vous pouvez les télécharger sur le site officiel de Node.js. De plus, vous aurez besoin d'un éditeur de texte pour écrire votre code. Vous pouvez utiliser n'importe quel éditeur de texte de votre choix, mais certains populaires incluent le code Visual Studio, l'atome et le texte sublime.
Comment puis-je installer le module nœud-wifi?
Vous pouvez installer Le module Node-Wifi utilisant NPM, qui est un gestionnaire de packages pour Node.js. Ouvrez votre terminal ou votre invite de commande et accédez au répertoire où vous souhaitez installer le module. Ensuite, exécutez la commande «NPM Install Node-Wifi». Cela téléchargera et installera le module Node-Wifi dans votre répertoire actuel.
Comment puis-je me connecter à un réseau Wi-Fi à l'aide du module Node-Wifi?
Le module Node-WiFi fournit Une fonction «connexion» que vous pouvez utiliser pour vous connecter à un réseau Wi-Fi. Vous devez transmettre un objet à cette fonction qui contient le SSID et le mot de passe du réseau. Voici un exemple:
var wifi = require ('node-wifi');
wifi.connect ({ssid: 'votre nom de réseau', mot de passe: 'votre mot de passe'}, fonction (err) {
if (err) {
console.log (err);
}
console.log ('connecté avec succès au réseau');
});
Comment puis-je rechercher des réseaux Wi-Fi disponibles?
Le module de nœud-wifi fournit une fonction «scan» que vous pouvez utiliser pour scanner pour les réseaux Wi-Fi disponibles. Cette fonction renvoie un tableau de réseaux. Chaque réseau est un objet qui contient des informations telles que le SSID, la force du signal et le type de sécurité. Voici un exemple:
var wifi = require ('node-wifi');
wifi.scan (fonction (err, réseaux) {
if (err) {
console.log (err);
}
console.log (réseaux);
});
comment puis-je me déconnecter d'un réseau Wi-Fi?
Le nœud- Le module WiFi fournit une fonction «déconnecter» que vous pouvez utiliser pour déconnecter d'un réseau Wi-Fi. Vous n'avez pas besoin de transmettre des arguments à cette fonction. Voici un exemple:
var wifi = require ('node-wifi');
wifi.disconnect (function (err) {
if (err) {
console.log (err. );
}
Console.log («Déconnecté avec succès du réseau»);
});
Comment puis-je obtenir l'état Wi-Fi actuel?
Le module Node-WiFi fournit une fonction «GetCurrentConnections» que vous pouvez utiliser pour obtenir l'état Wi-Fi actuel. Cette fonction renvoie un tableau de réseaux auxquels l'ordinateur est actuellement connecté. Voici un exemple:
var wifi = require ('node-wifi');
wifi.getCurrentConnections (fonction (err, currentconnections) {
if (err) {
console.log (err);
}
console.log (currentconnections);
});
comment puis-je gérer les erreurs dans le module de nœud-wifi?
Le nœud -Le module WIFI suit le modèle standard de gestion des erreurs Node.js. Toutes les fonctions prennent un rappel comme dernier argument. Ce rappel est une fonction qui prend deux arguments: un objet d'erreur et le résultat. Si une erreur se produit, l'objet d'erreur contiendra des informations sur l'erreur. Sinon, l'objet d'erreur sera nul et le résultat contiendra le résultat de l'opération.
Puis-je utiliser le module Node-WiFi pour gérer les réseaux Wi-Fi sur tous les systèmes d'exploitation?
Le module Node-WiFi est conçu pour fonctionner sur Windows, MacOS et Linux. Cependant, la fonctionnalité peut varier légèrement entre différents systèmes d'exploitation en raison de différences dans la façon dont ils gèrent les réseaux Wi-Fi.
Puis-je utiliser le module Node-Wifi avec d'autres modules Node.js?
Oui, vous pouvez utiliser le module Node-Wifi avec d'autres modules Node.js. Par exemple, vous pouvez l'utiliser avec le module Express pour créer un serveur Web qui affiche les réseaux Wi-Fi disponibles.
Comment puis-je contribuer au module de nœud-wifi?
Le nœud -Le module WIFI est un projet open-source, et les contributions sont les bienvenues. Vous pouvez contribuer en signalant des bogues, en suggérant de nouvelles fonctionnalités, en améliorant la documentation ou en écrivant du code. Pour contribuer, vous pouvez débarquer le projet sur GitHub, apporter vos modifications, puis soumettre une demande de traction.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds











JavaScript est la pierre angulaire du développement Web moderne, et ses principales fonctions incluent la programmation axée sur les événements, la génération de contenu dynamique et la programmation asynchrone. 1) La programmation axée sur les événements permet aux pages Web de changer dynamiquement en fonction des opérations utilisateur. 2) La génération de contenu dynamique permet d'ajuster le contenu de la page en fonction des conditions. 3) La programmation asynchrone garantit que l'interface utilisateur n'est pas bloquée. JavaScript est largement utilisé dans l'interaction Web, les applications à une page et le développement côté serveur, améliorant considérablement la flexibilité de l'expérience utilisateur et du développement multiplateforme.

Les dernières tendances de JavaScript incluent la montée en puissance de TypeScript, la popularité des frameworks et bibliothèques modernes et l'application de WebAssembly. Les prospects futurs couvrent des systèmes de type plus puissants, le développement du JavaScript côté serveur, l'expansion de l'intelligence artificielle et de l'apprentissage automatique, et le potentiel de l'informatique IoT et Edge.

Différents moteurs JavaScript ont des effets différents lors de l'analyse et de l'exécution du code JavaScript, car les principes d'implémentation et les stratégies d'optimisation de chaque moteur diffèrent. 1. Analyse lexicale: convertir le code source en unité lexicale. 2. Analyse de la grammaire: générer un arbre de syntaxe abstrait. 3. Optimisation et compilation: générer du code machine via le compilateur JIT. 4. Exécuter: Exécutez le code machine. Le moteur V8 optimise grâce à une compilation instantanée et à une classe cachée, SpiderMonkey utilise un système d'inférence de type, résultant en différentes performances de performances sur le même code.

Python convient plus aux débutants, avec une courbe d'apprentissage en douceur et une syntaxe concise; JavaScript convient au développement frontal, avec une courbe d'apprentissage abrupte et une syntaxe flexible. 1. La syntaxe Python est intuitive et adaptée à la science des données et au développement back-end. 2. JavaScript est flexible et largement utilisé dans la programmation frontale et côté serveur.

JavaScript est le langage central du développement Web moderne et est largement utilisé pour sa diversité et sa flexibilité. 1) Développement frontal: construire des pages Web dynamiques et des applications à une seule page via les opérations DOM et les cadres modernes (tels que React, Vue.js, Angular). 2) Développement côté serveur: Node.js utilise un modèle d'E / S non bloquant pour gérer une concurrence élevée et des applications en temps réel. 3) Développement des applications mobiles et de bureau: le développement de la plate-forme multiplateuse est réalisé par réact noral et électron pour améliorer l'efficacité du développement.

Cet article démontre l'intégration frontale avec un backend sécurisé par permis, construisant une application fonctionnelle EdTech SaaS en utilisant Next.js. Le frontend récupère les autorisations des utilisateurs pour contrôler la visibilité de l'interface utilisateur et garantit que les demandes d'API adhèrent à la base de rôles

J'ai construit une application SAAS multi-locataire fonctionnelle (une application EdTech) avec votre outil technologique quotidien et vous pouvez faire de même. Premièrement, qu'est-ce qu'une application SaaS multi-locataire? Les applications saas multi-locataires vous permettent de servir plusieurs clients à partir d'un chant

Le passage de C / C à JavaScript nécessite de s'adapter à la frappe dynamique, à la collecte des ordures et à la programmation asynchrone. 1) C / C est un langage dactylographié statiquement qui nécessite une gestion manuelle de la mémoire, tandis que JavaScript est dynamiquement typé et que la collecte des déchets est automatiquement traitée. 2) C / C doit être compilé en code machine, tandis que JavaScript est une langue interprétée. 3) JavaScript introduit des concepts tels que les fermetures, les chaînes de prototypes et la promesse, ce qui améliore la flexibilité et les capacités de programmation asynchrones.
