[RESOLU] Comment envoyer/recevoir des requêtes http en asynchrone avec Arduino UNO Wifi Rev2?

Bonjour,
Je voudrais contrôler une sorte de voitures à distance grâce à une carte Arduino UNO Wifi Rev2. Ma première piste était d'utiliser Wifinina pour créer un site sur l'ip locale, mais il est à ma connaissance possible d'envoyer que des requêtes synchrones et non asynchrones, demandant un rafraichissement de la page pour chaque requête. Sachant que mon but est de créer un joystick virtuel et d'envoyer sa position de manière fluide et efficace, il est impossible de devoir rafraîchir la page à chaque action. Ainsi, des requêtes asynchrones serait la solution, mais comment faire?
Merci pour vos réponses.

Ceci n'est pas très claire, je trouve.
Le serveur est sur ta voiture ?

Normalement le serveur HTTP est sur la voiture et te renvois une page WEB, qui fera par la suite des requetes à chaque action sur la télécommande virtuel qui ne neciterra pas forcément de retour autre qu'un code 200.
Après la possibilité d'avoir des requetes synchrones ou asynchrone ne dédent que de la librairie que tu utilise ou de ta volonter de le faire.
Par contre je ne comprends pas ta problèmatique.

Bonjour Terwal, merci de votre réponse. Je vais essayer d’être plus clair.
Je veux que ma box wifi agisse comme serveur(j’y aurais accès par site grâce à son adresse ip). Quand je bouge un joystick virtuel, je change l’URL qui est "http://xxx.xxx.x.xx/" en ajoutant quelque chose comme "test?la requête", que je traite dans la carte pour avancer les moteurs en fonction. Ceci demande un rafraîchissement pour changer la requête.

De ce que j’ai compris de mes tests, la carte crée la page web et la stocke sur la box wifi. C’est elle qui envoie les requêtes par l’intermédiaire de la box. Je ne saurais pas dire qui représente le serveur dans une communication web "normale".

Actuellement pour les requêtes synchrones j’utilise Wifinina. Cependant peut-être que j’ai mal compris le mot asynchrone mais quand je l’utilise je pense aux requêtes Ajax. Je sais créer un programme JavaScript qui envoie une telle requête mais je ne sais pas comment la récupérer sur la carte.

Merci d’avance,
GamerDev

Je suis désolé je suis long à la détente, mais c'est pire qu'avant :frowning:

Serveur quoi ?
Tu veux dire que ton application WEB de joystick virtuel, peux être situé à l'exterieur de chez toi.
Par exemple via ton téléphone, qui accédera à ta voiture, via la 5G et l'IP exterieur de ton domicile?
Dans ce cas, plutot que serveur on utilise plutot le mot routeur.

Dans ce cas là tu te trouve bien dans le cas que je décrivais dans mon précédent POST.
L'application WEB, comme tu parle de http://..., je suppose que ton joystick virtuel est une application WEB et que tu utilises alors de l'AJAX(le mieux de mon point de vue) ou un rafraichissement de la page(pas térrible :slight_smile: ).
Donc pour résumer!

  • si tu utilise la méthode que l'on pourrait qualifier de traditionnel, l'action de tes boutons de directions, rafraichisse la page compléte.
  • si tu utilise ma méthode AJAX, tu utilise le javascrpt pour faire ta requete sans rafraichir l'affichage de ta page WEB.
    La deuxiéme solution est donc a priviligier pour un confort utilisateur. Normalement l'AJAX est nettement plus "rapide", même si ce n'est pas forcément si pénalisant.

Non, ce n'est pas vraiment ça.
La carte ne crée pas de page web et encore moins la stocke sur la box wifi.
Elle n'envois pas vraiment la requete.

Ta carte crée un serveur WEB, qui va répondre à un client, c'est donc ta carte le serveur.
Tu n'a pas vraiment expliqué qui était le client, donc pour coller à ce que tu as décrit, je vais supposer que c'est un navigateur WEB(chrome, IE, ...) sur un Téléphone ou un PC, distant et passant par internet.

  • Dans ton client(Navigateur), tu va taper l'URL de ton serveur sur l'IP publique de ta maison http://xxx.xxx.x.xx/
    Ton navigateur va donc faire une réquête HTTP à cet adresse IP publique et le port 80.
    cette requête va arriver sur ta box internet, qui si elle est bien configurer, va rediriger(router) la requete sur le port 80, sur l'IP configurer dans ta box internet, normalement l'IP de ta carte Uno(il faut donc quel soit en IP fixe).
  • Ta carte traite cette requete et renvois une réponse contenant la page HTML à l'adresse IP qui a fait cette requête.
  • Ton navigateur affiche alors la page HTML, à l'écran.
  • Si l'utilisateur clique sur un bouton représantant ton joystick, que se soit en AJAX ou en rafraichissement, une nouvelle requete est faite, a priori en ajoutant un paramètre à la URI initial.
    La requête suit le même chemin que précédement, la différence se ferra uniquement coté navigateur(rafraichissement total de la page ou pas).

Donc d'un point de vue fonctionnel les deux sont possibles, mais en AJAX, le navigateur n'aura pas à rafraichir l'affichage de la page.

C'est à dire, comme le code qui utilise Wifinina est du coté serveur et l'AJAX coté client, qu'est ce que pour toi est synchrone ou pas?

Il faut que tu prennes par exemple l'exemple WiFiServer.cpp de la librairie Wifinina
Mais je n'ai pas l'impression que Wifinina, que je ne connais pas, presente un code pour faire un serveur HTTP facilement, comme peux le faire WiFiServer

pouvez vous nous en dire plus sur ce Joystick ? est-ce un "truc" fabriqué aussi avec Arduino ?

c'est vrai qu'un peu plus d'information ne peut pas faire de mal, après un joystick fabriqué avec un Arduino, n'est plus vraiment virtuel.

Bonjour,
Je vais préciser mon problème,

  • Je veux que ma sorte de voiture soit contrôler par un joystick comme ci-joint(visible côté client) dont le code est le suivant :
    index.html
<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Virtual Joystick</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div class="joystick" id="joystick">
      <div class="knob" id="knob"></div>
    </div>

    <script src="script.js"></script>
  </body>
</html>

styles.css

.joystick {
    width: 200px;
    height: 200px;
    background-color: #ccc;
    border-radius: 50%;
    position: relative;
    margin: 50px;
}

.knob {
  width: 50px;
  height: 50px;
  background-color: #333;
  border-radius: 50%;
  position: absolute;
  top: 75px;
  left: 75px;
  cursor: pointer;
}

script.js

const joystick = document.getElementById("joystick");
const knob = document.getElementById("knob");

let isDragging = false;

const joystickRect = joystick.getBoundingClientRect();
const joystickCenterX = joystickRect.left + joystickRect.width / 2;
const joystickCenterY = joystickRect.top + joystickRect.height / 2;

console.log(knob);

// Fonction pour obtenir les coordonnées du pointeur de la souris ou du toucher
function getCoordinates(event) {
  if (event.touches && event.touches.length) {
    return {
      x: event.touches[0].clientX,
      y: event.touches[0].clientY,
    };
  } else {
    return {
      x: event.clientX,
      y: event.clientY,
    };
  }
}

// Fonction pour mettre à jour la position du knob
function updateKnobPosition(event) {
  const coordinates = getCoordinates(event);

  // Calcul de la distance entre le centre du joystick et le pointeur
  const deltaX = coordinates.x - joystickCenterX;
  const deltaY = coordinates.y - joystickCenterY;
  const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

  // Si le pointeur dépasse le rayon du joystick, limiter la distance
  if (distance > joystickRect.width / 2) {
    const angle = Math.atan2(deltaY, deltaX);
    const newX = joystickCenterX + Math.cos(angle) * (joystickRect.width / 2);
    const newY = joystickCenterY + Math.sin(angle) * (joystickRect.width / 2);
    knob.style.left = newX - joystickRect.left - knob.offsetWidth / 2 + "px";
    knob.style.top = newY - joystickRect.top - knob.offsetHeight / 2 + "px";
  } else {
    knob.style.left =
      coordinates.x - joystickRect.left - knob.offsetWidth / 2 + "px";
    knob.style.top =
      coordinates.y - joystickRect.top - knob.offsetHeight / 2 + "px";
  }
}

// Événements de déclenchement lors du début du glissement
knob.addEventListener("mousedown", (event) => {
  isDragging = true;
  updateKnobPosition(event);
});

knob.addEventListener("touchstart", (event) => {
  isDragging = true;
  updateKnobPosition(event);
});

// Événements de déclenchement pendant le glissement
document.addEventListener("mousemove", (event) => {
  if (isDragging) {
    updateKnobPosition(event);
  }
});

document.addEventListener("touchmove", (event) => {
  if (isDragging) {
    updateKnobPosition(event);
  }
});

// Événements de déclenchement lors de la fin du glissement
document.addEventListener("mouseup", () => {
  isDragging = false;
  knob.style.left = "75px"; // Remet la position X du knob au centre
  knob.style.top = "75px"; // Remet la position Y du knob au centre
});

document.addEventListener("touchend", () => {
  isDragging = false;
  knob.style.left = "75px"; // Remet la position X du knob au centre
  knob.style.top = "75px"; // Remet la position Y du knob au centre
});
  • J'affiche ceci côté client en utilisant "client.println" de la bibliothèque Wifinina.

  • Puis je voudrais récupérer la position du joystick de manière asynchrone toutes les 0.25 secondes à peu près.

Comment faire ce dernier point. Pas besoin de forcément d'utiliser WiFiNINA mais c'est préférable. Il est aussi possible d'utiliser la carte comme point d'accès si c'est plus simple.

En vous remerciant,
GamerDev

donc votre Arduino fait serveur web et sait répondre à des requêtes

vous n'avez qu'à rajouter un petit bout de code supplémentaire qui émet les modification de position depuis votre fonction updateKnobPosition()

      // Émettre la requête AJAX avec les nouvelles coordonnées
      const xhr = new XMLHttpRequest();
      const url = window.location.href + `?x=${coordinates.x}&y=${coordinates.y}`;
      xhr.open("GET", url, true);
       xhr.onreadystatechange = function() {
         if (xhr.readyState === XMLHttpRequest.DONE && xhr.status != 200) {
           console.error("Erreur lors de l'envoi de la position du joystick!");
        }
      };
      xhr.send();

votre fonction devient donc

    // Fonction pour mettre à jour la position du knob et émettre la requête AJAX
    function updateKnobPosition(event) {
      const coordinates = getCoordinates(event);

      // Calcul de la distance entre le centre du joystick et le pointeur
      const deltaX = coordinates.x - joystickCenterX;
      const deltaY = coordinates.y - joystickCenterY;
      const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

      // Si le pointeur dépasse le rayon du joystick, limiter la distance
      if (distance > joystickRect.width / 2) {
        const angle = Math.atan2(deltaY, deltaX);
        const newX = joystickCenterX + Math.cos(angle) * (joystickRect.width / 2);
        const newY = joystickCenterY + Math.sin(angle) * (joystickRect.width / 2);
        knob.style.left = newX - joystickRect.left - knob.offsetWidth / 2 + "px";
        knob.style.top = newY - joystickRect.top - knob.offsetHeight / 2 + "px";
      } else {
        knob.style.left =
          coordinates.x - joystickRect.left - knob.offsetWidth / 2 + "px";
        knob.style.top =
          coordinates.y - joystickRect.top - knob.offsetHeight / 2 + "px";
      }

      // Émettre la requête AJAX avec les nouvelles coordonnées
      const xhr = new XMLHttpRequest();
      const url = window.location.href + `?x=${coordinates.x}&y=${coordinates.y}`;
      xhr.open("GET", url, true);
       xhr.onreadystatechange = function() {
         if (xhr.readyState === XMLHttpRequest.DONE && xhr.status != 200) {
           console.error("Erreur lors de l'envoi de la position du joystick!");
        }
      };
      xhr.send();
    }

côté Arduino vous recevrez une requête avec en paramètre x=123&y=456 qu'il vous suffira de décoder et vous retrournez simplement le code 200. L'envoi se fait à chaque modification de position.


j'ai tapé cela ici donc pas sûr à 100% que ça fonctionne

Pour un peu plus détailler la réponse de @J-M-L, il n'est pas necessaire de récupérer la position de ton joystick toutes les 0.25, ton joystick va envoyer sa nouvelle position à chaque modification.
A noter que là, l'envois de la requête du client à ta voiture est asynchrone.

Par contre comme indiqué dans mon précédent message, je ne pense pas que WIFInina fournisse de quoi gérer ton serveur de façon haut niveau. cela sera à toi de reception des trames TCP et de répondre correctement suivant le protocole HTTP.
Ton code sur l'Arduino avec WIFInima gére déjà la premiére requete HTTP qui renvois ta page HTML ?

il y a la classe WiFiServer et oui il faut décoder "à la main" la requête

cf un exemple

Merci beaucoup à vous deux,
Désolé de n'avoir pas répondu plus tôt,
Au lieu d'envoyer une requête GET, j'ai préféré POST que je décode certes à la main mais ce n'est pas un problème tant que ça marche. Pour définir la solution de ce post, je ne sais pas si :

  • j'envoie mon code comme je l'ai pas mal modifié(surtout le code html)

  • ou je marque celle de @J-M-L post #8 qui donne l'idée.

Dites-le moi svp.
Je vais créer un nouveau post car j'ai un problème avec la library AFMotor : Problèmes avec la library AFMotor.
Encore merci pour votre aide!

Peu importe. Si vous postez votre code c’est aussi une solution

Ok merci je préfère votre proposition, c'est plus général je pense.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.