Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Sécurisez votre Arduino avec le déverrouillage par motif web – Configuration facile et contrôle à distance

Composants et fournitures

Composant Quantité
Arduino UNO 1
Shield WiFi PHPoC pour Arduino 1
Servomoteur Seeed SG92R 1
Fils de connexion (jumper wires) 1

À propos de ce projet

Introduction

Si vous êtes débutant, je vous recommande de consulter les tutoriels suivants :

Vous connaissez probablement le motif de déverrouillage utilisé sur les smartphones. Cette fonctionnalité est désormais disponible sur Arduino. Elle empêche les personnes non autorisées de contrôler ou de surveiller votre Arduino.

Vous pouvez réutiliser librement le code de ce projet pour d'autres applications. Pour simplifier, j'utilise le contrôle d'un servomoteur comme exemple.

Ce projet s'inspire de deux projets conçus pour la plateforme PHPoC :

Je les ai adaptés pour Arduino.

J'ai utilisé le Shield WiFi PHPoC pour connecter l'Arduino à Internet car :

Le Shield PHPoC possède des applications web intégrées qui permettent à l'utilisateur de contrôler/surveiller l'Arduino sans connaissances en programmation web. De plus, il permet aux développeurs web de créer leurs propres applications et de les stocker sur le shield.

Démonstration

Une démonstration visuelle montre l'interface de déverrouillage par motif sur navigateur web et le contrôle du servomoteur après authentification réussie.

Flux de données

Navigateur web ←→ Shield WiFi PHPoC ←→ Arduino

Sécurisez votre Arduino avec le déverrouillage par motif web – Configuration facile et contrôle à distance

Fonctionnement

Lorsque l'utilisateur dessine son motif sur le navigateur web, celui-ci est converti en une chaîne de caractères. Cette chaîne est envoyée à l'Arduino via WebSocket (par l'intermédiaire du Shield PHPoC).

À la réception, l'Arduino compare la chaîne reçue avec le motif préenregistré. S'ils correspondent, l'Arduino renvoie le code ACCEPTED (202) et définit la variable authenticated sur true. Sinon, il renvoie DENIED (401) et met la variable à false.

Lorsqu'une commande de contrôle est reçue, l'Arduino vérifie d'abord la variable authenticated. Si true, il exécute la commande. Si false, il renvoie DENIED.

Correspondance des motifs

Sécurisez votre Arduino avec le déverrouillage par motif web – Configuration facile et contrôle à distance

Le motif est converti en chaîne. Par exemple, sur l'image ci-dessus, la chaîne est "1, 4, 8, 6, 3".

Un délai d'expiration est configuré. Après une période d'inactivité, l'authentification expire et l'utilisateur doit redessiner le motif pour déverrouiller à nouveau.

Le code source comprend deux fichiers :

Étapes de mise en œuvre

Configuration WiFi du Shield PHPoC

Suivez cette instruction.

Téléversement de l'interface web sur le Shield PHPoC

Écriture du code Arduino

  • Installez la bibliothèque PHPoC pour Arduino sur l'IDE Arduino (voir l'instruction).
  • Consultez le code source dans la section code.
  • Compilez et téléversez sur l'Arduino via l'IDE Arduino.

Tester le projet

  • Cliquez sur le bouton série dans l'IDE Arduino pour voir l'adresse IP.
  • Ouvrez un navigateur web, saisissez https://adresse_ip/unlock.php
  • Cliquez sur le bouton de connexion et testez.

Meilleur kit de démarrage Arduino pour débutant

Si vous cherchez un kit Arduino, consultez Le meilleur kit Arduino pour débutants.

Références des fonctions

  • Bibliothèque Servo Arduino
  • Servo.attach()
  • Servo.write()
  • Servo.writeMicroseconds()
  • Servo.read()
  • Servo.attached()
  • Servo.detach()
  • Serial.begin()
  • Serial.println()
  • delay()
  • millis()
  • Boucle for
  • Boucle while
  • if else
  • loop()
  • setup()
  • String.toInt()
  • String.substring()
  • String.indexOf()
  • String.remove()
  • String.equals()

Code

unlock.php (PHP)

Interface utilisateur web

<!DOCTYPE html> <html> <head> <title>Arduino - PHPoC Shield</title> <meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7"> <meta charset="utf-8"> <style> body { text-align: center; font-size: width/2pt; } h1 { font-weight: bold; font-size: width/2pt; } h2 { font-weight: bold; font-size: width/2pt; } button { font-weight: bold; font-size: width/2pt; } </style> <script> var CMD_AUTH = 0; var CMD_CTRL = 1; var ws; var authorized = false; /* variable de déverrouillage */ var unlock_width = 400, unlock_height = 400; var unlock_inner_radius = 14; var unlock_middle_radius = 22; var unlock_outer_radius = 34; var unlock_gap = 140; var unlock_touch_state = 0; var unlock_touch_x = 0, unlock_touch_y = 0; var unlock_touch_list = new Array(); var unlock_ratio = 1; /* variable de contrôle : modifiez selon votre application */ var servo_width = 401, servo_height = 466; var servo_pivot_x = 200, servo_pivot_y = 200; var servo_bracket_radius = 160, servo_bracket_angle = 0; var servo_bracket_img = new Image(); var servo_click_state = 0; var servo_last_angle = 0; var servo_mouse_xyra = {x:0, y:0, r:0.0, a:0.0}; servo_bracket_img.src = "servo_bracket.png"; function init() { /* initialisation partie déverrouillage */ var unlock = document.getElementById("unlock"); unlock.width = unlock_width; unlock.height = unlock_height; unlock.addEventListener("touchstart", unlock_mouse_down); unlock.addEventListener("touchend", unlock_mouse_up); unlock.addEventListener("touchmove", unlock_mouse_move); unlock.addEventListener("mousedown", unlock_mouse_down); unlock.addEventListener("mouseup", unlock_mouse_up); unlock.addEventListener("mousemove", unlock_mouse_move); var ctx = unlock.getContext("2d"); ctx.translate(unlock_width/2, unlock_height/2); ctx.shadowBlur = 20; ctx.shadowColor = "LightGray"; ctx.lineCap="round"; ctx.lineJoin="round"; /* initialisation partie contrôle */ var servo = document.getElementById("servo"); servo.width = servo_width; servo.height = servo_height; servo.style.backgroundImage = "url('/servo_body.png')"; servo.addEventListener("touchstart", servo_mouse_down); servo.addEventListener("touchend", servo_mouse_up); servo.addEventListener("touchmove", servo_mouse_move); servo.addEventListener("mousedown", servo_mouse_down); servo.addEventListener("mouseup", servo_mouse_up); servo.addEventListener("mousemove", servo_mouse_move); ctx = servo.getContext("2d"); ctx.translate(servo_pivot_x, servo_pivot_y); update_view(); } function connect_onclick() { if(ws == null) { var ws_host_addr = ""; if((navigator.platform.indexOf("Win") != -1) && (ws_host_addr.charAt(0) == "[")) { ws_host_addr = ws_host_addr.replace(/[\[\]]/g, ''); ws_host_addr = ws_host_addr.replace(/:/g, "-"); ws_host_addr += ".ipv6-literal.net"; } ws = new WebSocket("ws://" + ws_host_addr + "/web_pattern", "text.phpoc"); document.getElementById("ws_state").innerHTML = "CONNECTING"; ws.onopen = ws_onopen; ws.onclose = ws_onclose; ws.onmessage = ws_onmessage; } else ws.close(); } function ws_onopen() { document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>"; document.getElementById("bt_connect").innerHTML = "Disconnect"; update_view(); } function ws_onclose() { document.getElementById("ws_state").innerHTML = "<font color='gray'>CLOSED</font>"; document.getElementById("bt_connect").innerHTML = "Connect"; ws.onopen = null; ws.onclose = null; ws.onmessage = null; ws = null; authorized = false; update_view(); } function ws_onmessage(e_msg) { e_msg = e_msg || window.event; var resp = parseInt(e_msg.data); if(resp == 202) authorized = true; else if(resp == 401) authorized = false; else console.log("unknown:" + resp); update_view(); } function update_view() { if(!authorized) unlock_update_view(); else servo_update_view(); } function unlock_update_view() { document.body.style.backgroundColor = "black"; document.body.style.color = "white"; var unlock_area = document.getElementById('unlock_area'); var control_area = document.getElementById('control_area'); unlock_area.style.display = 'block'; control_area.style.display = 'none'; var unlock = document.getElementById("unlock"); var ctx = unlock.getContext("2d"); ctx.clearRect(-unlock_width/2, -unlock_height/2, unlock_width, unlock_height); // dessiner points et lignes touchés ctx.lineWidth = 10; ctx.strokeStyle="white"; ctx.globalAlpha=1; ctx.beginPath(); for (var i = 0; i < unlock_touch_list.length; i++) { var temp = unlock_touch_list[i] - 1; var x = temp % 3 - 1; var y = Math.floor(temp / 3) - 1; ctx.lineTo(x*unlock_gap, y*unlock_gap); } if(unlock_touch_state) ctx.lineTo(unlock_touch_x, unlock_touch_y); ctx.stroke(); for (var i = 0; i < unlock_touch_list.length; i++) { var temp = unlock_touch_list[i] - 1; var x = temp % 3 - 1; var y = Math.floor(temp / 3) - 1; ctx.globalAlpha=0.2; ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(x*unlock_gap, y*unlock_gap, unlock_outer_radius, 0, 2 * Math.PI); ctx.fill(); } // dessiner la base for(var y = -1; y <= 1; y++) { for(var x = -1; x <= 1; x++) { ctx.globalAlpha=0.5; ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(x*unlock_gap, y*unlock_gap, unlock_middle_radius, 0, 2 * Math.PI); ctx.fill(); ctx.globalAlpha=1; ctx.fillStyle = "Cyan"; ctx.beginPath(); ctx.arc(x*unlock_gap, y*unlock_gap, unlock_inner_radius, 0, 2 * Math.PI); ctx.fill(); } } } function unlock_process_event(event) { if(event.offsetX) { unlock_touch_x = event.offsetX - unlock_width/2; unlock_touch_y = event.offsetY - unlock_height/2; } else if(event.layerX) { unlock_touch_x = event.layerX - unlock_width/2; unlock_touch_y = event.layerY - unlock_height/2; } else { unlock_touch_x = (Math.round(event.touches[0].pageX - event.touches[0].target.offsetLeft)) - unlock_width/2; unlock_touch_y = (Math.round(event.touches[0].pageY - event.touches[0].target.offsetTop)) - unlock_height/2; } for(var i = 1; i <= 9; i++) { if(i == unlock_touch_list[unlock_touch_list.length - 1]) continue; var idx_x = (i-1)%3 - 1; var idx_y = Math.floor((i-1)/3) - 1; var center_x = idx_x*unlock_gap; var center_y = idx_y*unlock_gap; var dist = Math.sqrt( (unlock_touch_x - center_x)*(unlock_touch_x - center_x) + (unlock_touch_y - center_y)*(unlock_touch_y - center_y) ); if(dist < unlock_outer_radius) { unlock_touch_list.push(i); unlock_touch_state = 1; break; } } update_view(); } function unlock_mouse_down() { if(ws == null || authorized) return; event.preventDefault(); unlock_process_event(event); } function unlock_mouse_up() { if(ws == null || authorized) return; event.preventDefault(); if(ws != null && authorized == false) send_to_Arduino(CMD_AUTH, unlock_touch_list.toString()); unlock_touch_state = 0; unlock_touch_list.splice(0, unlock_touch_list.length); update_view(); } function unlock_mouse_move() { if(ws == null || authorized) return; event.preventDefault(); if(authorized) return; unlock_process_event(event); } function servo_update_view() { document.body.style.backgroundColor = "white"; document.body.style.color = "black"; var unlock_area = document.getElementById('unlock_area'); var control_area = document.getElementById('control_area'); unlock_area.style.display = 'none'; control_area.style.display = 'block'; /* modifier la zone de contrôle ici */ var servo = document.getElementById("servo"); var ctx = servo.getContext("2d"); ctx.clearRect(-servo_pivot_x, -servo_pivot_y, servo_width, servo_height); ctx.rotate(servo_bracket_angle / 180 * Math.PI); ctx.drawImage(servo_bracket_img, -servo_pivot_x, -servo_pivot_y); ctx.rotate(-servo_bracket_angle / 180 * Math.PI); } function check_range_xyra(event, servo_mouse_xyra) { var x, y, r, a, rc_x, rc_y, radian; var min_r, max_r, width; if(event.touches) { var touches = event.touches; x = (touches[0].pageX - touches[0].target.offsetLeft) - servo_pivot_x; y = servo_pivot_y - (touches[0].pageY - touches[0].target.offsetTop); min_r = 60; max_r = servo_pivot_x; width = 40; } else { x = event.offsetX - servo_pivot_x; y = servo_pivot_y - event.offsetY; min_r = 60; max_r = servo_bracket_radius; width = 20; } /* conversion coordonnées cartésiennes vers polaires */ r = Math.sqrt(x * x + y * y); a = Math.atan2(y, x); servo_mouse_xyra.x = x; servo_mouse_xyra.y = y; servo_mouse_xyra.r = r; servo_mouse_xyra.a = a; radian = servo_bracket_angle / 180 * Math.PI; /* rotation des coordonnées */ rc_x = x * Math.cos(radian) - y * Math.sin(radian); rc_y = x * Math.sin(radian) + y * Math.cos(radian); if((r < min_r) || (r > max_r)) return false; if((rc_y < -width) || (rc_y > width)) return false; return true; } function servo_mouse_down() { if(event.touches && (event.touches.length > 1)) servo_click_state = event.touches.length; if(servo_click_state > 1) return; if(check_range_xyra(event, servo_mouse_xyra)) { servo_click_state = 1; servo_last_angle = servo_mouse_xyra.a / Math.PI * 180.0; } } function servo_mouse_up() { servo_click_state = 0; } function servo_mouse_move() { var angle; if(event.touches && (event.touches.length > 1)) servo_click_state = event.touches.length; if(servo_click_state > 1) return; if(!servo_click_state) return; if(!check_range_xyra(event, servo_mouse_xyra)) { servo_click_state = 0; return; } angle = servo_mouse_xyra.a / Math.PI * 180.0; if((Math.abs(angle) > 90) && (angle * servo_last_angle < 0)) { if(servo_last_angle > 0) servo_last_angle = -180; else servo_last_angle = 180; } servo_bracket_angle += (servo_last_angle - angle); servo_last_angle = angle; if(servo_bracket_angle > 90) servo_bracket_angle = 90; if(servo_bracket_angle < -90) servo_bracket_angle = -90; servo_update_view(); send_to_Arduino(CMD_CTRL, Math.floor(servo_bracket_angle)) debug = document.getElementById("debug"); debug.innerHTML = Math.floor(servo_bracket_angle); event.preventDefault(); } function send_to_Arduino(cmd, data) { if(ws.readyState == 1) { ws.send(cmd + ":" + data + "\r\n"); } } window.onload = init; </script> </head> <body> <p> <h1>Arduino - Web Pattern Unlock</h1> </p> <div id="unlock_area" style="display:block;"> <canvas id="unlock"></canvas> </div> <div id="control_area" style="display:none;"> <canvas id="servo"></canvas> <p>Angle : <span id="debug">0</span></p> </div> <h2> <p>WebSocket : <span id="ws_state">null</span></p> <button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button> </h2> </body> </html>

ArduinoUnlockExample (Arduino)

/* serveur web arduino - déverrouillage par motif */ #include "SPI.h" #include "Phpoc.h" #include  #define CMD_AUTH 0 #define CMD_CTRL 1 #define ACCEPTED "202" #define UNAUTHORIZED "401" PhpocServer server(80); Servo servo; String pattern; bool authenticated; unsigned long timeout; unsigned long lastActiveTime; void setup() { Serial.begin(9600); while(!Serial) ; Phpoc.begin(PF_LOG_SPI | PF_LOG_NET); //Phpoc.begin(); server.beginWebSocket("web_pattern"); Serial.print("Adresse serveur WebSocket : "); Serial.println(Phpoc.localIP()); servo.attach(8); // attache le servomoteur sur la broche 8 servo.write(90); pattern = String("1,4,8,6,3"); authenticated = false; timeout = 10000; // 10000 millisecondes lastActiveTime = 0; } void loop() { // attendre un nouveau client : PhpocClient client = server.available(); if (client) { String data = client.readLine(); if(data) { int pos = data.indexOf(':'); int cmd = data.substring(0, pos).toInt(); if(cmd == CMD_AUTH) { String reqPattern = data.substring(pos+1); reqPattern.remove(reqPattern.indexOf(13)); reqPattern.remove(reqPattern.indexOf(10)); if(pattern.equals(reqPattern)) { authenticated = true; sendResponse(ACCEPTED, 3); lastActiveTime = millis(); } else { //Serial.print(reqPattern); authenticated = false; sendResponse(UNAUTHORIZED, 3); } } else if(cmd == CMD_CTRL) { if(authenticated) { int angle = data.substring(pos+1).toInt(); //angle = map(angle, -90, 90, 0, 180); angle = map(angle, 90, -90, 0, 180); servo.write(angle); lastActiveTime = millis(); Serial.println(angle); } else { sendResponse(UNAUTHORIZED, 3); } } } } if (authenticated && ((millis() - lastActiveTime) > timeout)){ authenticated = false; sendResponse(UNAUTHORIZED, 3); } } void sendResponse(char *data, int len) { server.write(data, len); }

Schéma de câblage

Sécurisez votre Arduino avec le déverrouillage par motif web – Configuration facile et contrôle à distance

Processus de fabrication

  1. L'évolution et la production des patrons de couture industriels
  2. Système d'éclairage DMX piloté par web – Contrôleur maître Arduino
  3. Construire un Spybot Arduino piloté par Bluetooth
  4. FlickMote : Télécommande IR à gestes pour maison connectée
  5. TV-B-Gone DIY Arduino : Télécommande universelle pour toutes les TV
  6. Construire une horloge maître LED personnalisée avec alarme – Visible à 12 mètres
  7. Find Me : Localisateur d'objets intelligent avec Arduino et Bluetooth
  8. Solutions d'alimentation optimisées pour projets Arduino
  9. Morpion sur matrice LED MAX7219 avec boîtier en carton