Serveur domotique raspberry pi + arduino

J'ai utilisé ce tuto :
http://www.fraspberrypi.fr/post/auto-heberger-un-blog-dotclear-sur-raspberry-pi-partie-1
L' img raspian est optimisé pour un serveur sous lighttpd plus léger qu'apache..

le mieux est quand même la liaison eth entre le nono et le rasp, histoire de déporter ton nono plus loin.

Je comprends pas!! mon RPI est connecté sur ma freebox en ethernet donc je ne peux pas les connecter tout les 2 en eth !
comment je fais ensuite pour me connecter sur le RPI par l' IP qui est fixe ?

Mon problème actuellement est que je n'ai pas de liaison (socket,format json et web ajax) entre le nono et le RPI par l' USB...

Désolé je me suis mal expliqué je récapitule:
Le serveur sous PC serveur Wamp marche trés bien , la liaison de donnée (socket,format json et web ajax) passe par Eth.

Le serveur RPI branché en Eth sur la Box et l'arduino branché sur le sur port USB du RPI, dont le problème est comment envoyer les infos (socket,format json et web ajax) par le port USB??

pour l'iso du rapsberry, tu en trouveras ici Raspberry Pi OS – Raspberry Pi

Je comprends pas!! mon RPI est connecté sur ma freebox en ethernet donc je ne peux pas les connecter tout les 2 en eth !
comment je fais ensuite pour me connecter sur le RPI par l' IP qui est fixe ?

suffit de lui donner une ip fixe sur le réseau (192.168.0.xxx de mèmoire pour le FB)
http://webadonf.net/2011/02/attribuer-une-ip-fixe-a-debian-lenny/

après tu peux soit :
passer par le réseau pour envoyer au nono les instruction via le rapsberry
passer par usb, le nono connecté au rapsberry

en fait, c'est comme si tu déportais ton wamp ailleurs, ni plus ni moins.

L'ISO du Rasp me va trés bien et j'ai déja une IP fixe.

Voici ce que je veux faire :

Mon but est de pouvoir me connecter en local et extérieur (PC ou mobile ) , et de pouvoir commander l'arduino ou de recevoir des infos de celui ci...
Pour cela je me connecte sur l'IP + port du RPI pour avoir accès au serveur RPI dont les pages sont stocké sur la clé USB.

Mon ancien code (socket,format json et web ajax) ne fonctionne pas dans cette config ci , normal car utilise le port ethernet pour transfert des données.
Comment modifier mon code pour que les différentes commandes envoyé dur RPI vers l'arduino et inversement passent par le port USB ??

J'ai essayé sous win xp un :
$port = fopen("COM3", "w"); arduino branché en USB sur PC (com3)
fwrite($port, "a");
fclose($port);

mais cela me donne " Warning: fopen(COM3): failed to open stream: No such file or directory in "

Que faire??

Comment étais tu connecté avant (entre le PC et l'Arduino) ?

Si ton serveur LAMP/WAMP/PC discutait par Ethernet avec ton Arduino, la solution de base est de reproduire le même comportement (en gros tu te contentes de remplacer le PC par le RPi).

Si ton serveur PC discutait par USB/Série avec l'Arduino, idem : tu remplace le PC avec le RPi et au lieu d'utiliser COMx: tu utilises /dev/sttyx

L'USB est une liaison série. Tu ne peut pas faire passer des sockets TCP dessus.
Tu ne peut donc pas sans revoir complètement ton architecture passer d'une solution Arduino connecté en Ethernet a une solution Arduino connectée en USB.

Donc pour aller plus loin, dis nous plus précisement qu'elle est ton architecture matérielle (connections) et logicielle (flux de données) actuelle basée PC, et nous pourrons alors te guider vers ce qu'il faut changer pour atteindre la config décrite dans ton précédent message.

Ma config opérationnelle d'avant :
matérielle:

  • arduino duemilanove
  • ethernet shield
  • Pc sous win 7
  • freebox
    logicielle:
  • serveur wamp et site dans PC.

J'utilise la liaison ethernet (pc<=>Box et box<=>arduino par ethernet shield) pour le flux de donnée grâce au socket,format json et web ajax (voir lien 1er msg ; que tu connais très bien).

Nouvelle config:
Maintenant j'ai installé le serveur lighttpd et site sur le RPI (RPI et BOX relié par eth) , branché l'arduino sur le RPI par l'USB (et donc enlever la carte ethernet shield).
Je voudrais pouvoir faire transiter les infos par le port USB.
Donc comment transposer mon code pour atteindre cela?

Si ton serveur LAMP/WAMP/PC discutait par Ethernet avec ton Arduino, la solution de base est de reproduire le même comportement (en gros tu te contentes de remplacer le PC par le RPi).

En fait OUI, je dois garder l'ethernet shield et la relier sur la box , ainsi que le RPI relié sur la box en eth et cela devrai faire l'affaire...

En fait OUI, je dois garder l'ethernet shield et la relier sur la box , ainsi que le RPI relié sur la box en eth et cela devrai faire l'affaire...

Et oui ca marche...
Mais j'aurai préféré passer par le port USB car cela me permettrait d'enlever l'ethernet shield et donc de récupérer d'autres pin utilisable de l'arduino, ainsi que de n'avoir qu'un cable eth connecté a la freebox car la plus de dispo..

S'il y a moyen par l'USB je suis preneur et je verrai par la suite quel moyen je garderai en fonction de mes besoins..
Merci.

Le passage de ta solution actuelle à une solution via USB peut être de moyen à lourd.

En fait tout dépend exactement du flux de données entre les 3 éléments que sont :

  • le navigateur
  • le serveur Web
  • l'Arduino

Ton serveur Web fournit une page HTML au Navigateur
Mais ensuite comment la page communique t'elle avec le l'Arduino :

  1. communication directe : le code Javascript de la page (qui s'exécute dans le navigateur) utilise websocket ou Ajax directement avec l'Arduino
  2. communication indirecte : le code Javascript de la page cause avec le serveur Web (script PHP ou autre) qui ensuite communique avec l'Arduino

Dans le 2nd cas, tu n'a besoin de ne changer que le code coté serveur Web pour communiquer avec l'Arduino par une liaison série au lieu d'Ethernet
Dans le 1er cas, ce n'est pas possible sans d'abord se ramener au 2nd cas.

Il faut que tu précises ce que tu fait exactement.

J'espère que tu comprends les distinction que je fais car elles sont fondamentalement différentes.

+1 avec barbdor.
il y a une autre solution aussi, mettre un adaptateur USB-Réseau.

Sur mon serveur ma page php contient les scripts jquery.min.js et init.js
la page php appelle des fonctions dans init.js tel que

function emet( lamp,value, ack)
{
  var textejson = {"str":0x02,"len":0x04, "cmd":0x03, "dt1":lamp, "dt2":value, "dt3":ack, "end":0x03 };
  envoie(textejson);
}
function envoie(textejson)
{
  jQuery.post("socket.php", textejson,
 function(data)
 {
 parseJSon(JSON.stringify(data));
 }, "json");


}
function parseJSon(dJson)
{
  log(dJson);

  var duino = eval('(' + dJson + ')');
  switch(duino.cmd)
  {
    case 0x02:
      digitalWriteResp(duino.data1, duino.data2, duino.data3);
    break;
    case '2':
      digitalWriteResp(duino.data1, duino.data2, duino.data3);
    break;
    case 2:
      digitalWriteResp(duino.data1, duino.data2, duino.data3);
    break;
  }
  
}

et le fichier socket.php

<?php

$msg = "";
$buffer = null;

$msg = file_get_contents("php://input"); // on ne reprend que les données utiles et non l'intégralité de la requête 
$host="xxx.xxx.xxx.xxx";
$port="xxxx";

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); //création du socket
socket_connect($socket, $host, $port); //connection du socket
socket_write($socket,$msg,strlen($msg)); //envoie des données POST

do
{
  if(isset($buffer)) // si buffer contien des donnees
    echo $buffer; // reponse à la requête javascript
}
while(@socket_recv($socket,$buffer,32,0) != 0); // on attend la reponse (=! 0) sur le socket

socket_close($socket); //fermeture du socket
?>

Désolé je ne saurai pas vous expliqué plus. En espérant que cela vous aide a comprendre comment cela marche chez moi...

Donc si je comprend bien tu es déjà dans le 2nd cas

Page [Javascript/JQuery] --(post)--> Serveur web

 --(tcp-socket)--> Arduino [EthernetServer]

Je dirais que tu es dans le cas le plus simple pour migrer vers une liaison USB/Serial entre ton RPi et ton Arduino.

En effet coté Arduino, il va te falloir passer à Serial au lieu de EthernetServer. Cela va dans le sens d'une simplification du code car tu n'auras plus besoin de gérer un serveur et une connexion : la connexion série est toujours présente.

Coté PHP il va falloir remplacer la gestion socket par une gestion de port série.
Une rapide recherche google et je vois qu'il y a probablement 2 méthodes pour faire cela :
- la lib intégré à PHP "Direct I/O" http://php.net/manual/en/book.dio.php
- une lib externe dédiée serial : http://code.google.com/p/php-serial/

et je tombe par hasard sur un article qui parle d'utiliser la lib php-serial avec un RPi : http://www.raspberrypi.org/phpBB3/viewtopic.php?f=34&t=12000 (en fait c'est un gars qui a des problèmes parce que ca marche pas).

Je dirais pas encore tout a fait "Total Bonheur" mais je pense qu'on s'en rapproche.

Je suggère les étapes suivantes :
1) Etablir la liaison série entre RPi et Arduino
- Flasher dans ton Arduino depuis PC un sketch qui configure Serial à 9600b et qui fait Serial.println("Hello world!" ); delay(1000 );
- Brancher l'Arduino sur le port USB du RPi (il peut être prudent d'alimenter l'Arduino sur son entrée 6-9V pour éviter de trop tirer sur l'alim USB du RPi qui n'est pas réputée pour être très costaude).
- Attendre quelques instants
- taper la commande "dmesg" qui devrait rapporter que le port USB a été monté comme une liaison série du genre /dev/sttyUSBx" ou quelque chose du genre (trop fatiqué pour essayer moi même ce soir)
- taper la commande "cat /dev/xxxx" avec le nom de device ci-dessus
- Si tout se passe bien, tu devrais avoir les HelloW orld qui s'affichent dans la console
(J'ai fait ca avec une leonardo sur mon WR703N et il n'y avait aps besoin de régler la vitesse du port série coté Linu. Avec une UNO possible qu'il faille d'abord configurer le port série Linux et je sais pâ faire)

2) Apprendre à se servir de la php-serial ou DirectI/O pour communiquer entre PHP et Arduino
Note que PHP peut aussi s'utiliser en ligne de commande sans Web comme un langage de script en utilisant la commande "php moncode.php" ce qui est plus facile pour faire ce genre de test que de la faire via un serveur web.

3) Modifier ton PHP et ton sketch pour passer au dialogue série.

J'espère avoir été clair sur les étapes.
Si un [s]manchot[/s] pingouin ;) traine par là, il pourra te donner plus de détails sur le fonctionnement des ports série sur Linux, moins je suis encore trop imbibé de Windows XD.

Merci pour les infos, je vais étudier cela ...
J'ai aussi une WR703N non flashé OpenWrt, et pour l'instant pas trouvé quoi en faire si tu as des idées a me proposer ...

Pour avoir essayé, le dev sur WR703N est pas évident.
Je pense que sur RPi c'est plus facile comme c'est plus ou moins une Debian propre.

Mais tu peux commencer par bosser sur Linux PC puis porter petit a petit sur RPi.

J'utilise un Xbuntu dans un VMWare player avec QTCreator comme IDE pour editer, compiler et debugger.
Quand ton code marche sur PC, tu peux passer et le recompiler sur RPi avec makefile sans IDE car il est déjà bon à 99.9%.

bonjour,
avec un uno r3, c'est /dev/ACM0 sur le RPI.

après pour envoyer des commandes via php sur l'usb, il faut donner les droits à apache pour le faire.
après avec un truc de ce genre

$string="coucou";
$port = '/dev/ACM0';
$handle = fopen($port, 'w');
$contents = fwrite($handle, $string);
fclose($handle);

le mieux est d'utiliser un daemon, regarde ici http://open3600.fast-mail.nl/tiki-index.php
tu pourras t'en inspirer, on fait ca pour connecter une station météo avec linux et envoyer les données recues par usb vers apache/mysql.

EDIT :
pour donner les droits sur l'usb à apache (j'ai oublié de mettre la commande :slight_smile: )

sudo chown apache2:apache2 /dev/ttyACM0

j'arrive a envoyer un code en php pour allumer la led sur l'arduino par le port usb grace au code suivant:

<?php
 exec("mode com3: BAUD=9600 PARITY=N data=8 stop=1 xon=off dtr=off");
 $fp = fopen("COM3", "w+");
 fwrite($fp, "m1 off");
 fclose($fp);
 ?>

code arduino:

char inData[20]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character

void setup(){

  Serial.begin(9600);
  Serial.write("Power On");
}
char Comp(char* This){
  while(Serial.available() > 0) // Don't read unless
    // there you know there is data
  {
    if(index < 19) // One less than the size of the array
    {
      inChar = Serial.read(); // Read a character
      inData[index] = inChar; // Store it
      index++; // Increment where to write next
      inData[index] = '\0'; // Null terminate the string
    }
  }
  if(strcmp(inData,This)  == 0){
    for(int i=0;i<19;i++){
      inData[i]=0;
    }
    index=0;
    return(0);
  }
  else{
    return(1);
  }
}
void loop()
{
  if(Comp("m1 on")==0){
     digitalWrite(8,HIGH);
     Serial.write(" On");
  }
  if(Comp("m1 off")==0){
     digitalWrite(8,LOW);
     Serial.write(" Off");
  }
}

Maintenant sur mon ancien code arduino il décodait un message json genre :
var textejson = {"str":0x02,"len":0x04, "cmd":0x08, "dt1":1, "dt2":1, "dt3":1, "end":0x03 };

je ne sais pas comment faire pour changer mon code php pour pouvoir envoyer cette trame json par le port usb vers l'arduino.

Un indice??

Tu veux dire envoyer par PHP une chaine JSON à l'Arduino ?
Ca devrait être du genre :

fwrite($fp, "{ \"str\":0x02, \"len\":0x04, \"cmd\":0x08, \"dt1\":1, \"dt2\":1, \"dt3\":1, \"end\":0x03  }" );

Et si les valeurs à passer sont des variables PHP de même nom:

fwrite($fp, "{ \"str\":" . $str . ", \"len\":" . $len . ", \"cmd\":" . $cmd . ", \"dt1\":" . $dt1 . ", \"dt2\":" . $dt2 . ", \"dt3\":" . $dt3 . ", \"end\":" . $end ." }" );

Si ta question est dans l'autre sens : comment récupérer en PHP des variables que l'Arduino transmet en JSON, je pense qu'il va falloir simplifier le format et écrire un petit "parser" de réponses car je ne connais pas d'équivalent de la fonction d'exécution du Javascript qui permet de traiter des réponse JSON (qui sont en fait du code Javascript).

pas trop de temps aujourd'hui j'essayerai fwrite($fp, "{ \"str\":0x02, \"len\":0x04, \"cmd\":0x08, \"dt1\":1, \"dt2\":1, \"dt3\":1, \"end\":0x03  }" );

et par la suite oui il faudrait faire l'inverse récupérer en PHP des variables que l'Arduino transmet en JSON.

Merci.

archibal11:
pas trop de temps aujourd'hui j'essayerai fwrite($fp, "{ \"str\":0x02, \"len\":0x04, \"cmd\":0x08, \"dt1\":1, \"dt2\":1, \"dt3\":1, \"end\":0x03  }" );

et par la suite oui il faudrait faire l'inverse récupérer en PHP des variables que l'Arduino transmet en JSON.

Merci.

bonjour,
ca pourrait ressembler à un truc comme ca

$retour = "str":0x02, "len":0x04, "cmd":0x08, "dt1":1, "dt2":1, "dt3":1,"end":0x03 ;
$resultat = explode ('":',$retour);
$str = $resultat[0];
$len = $resultat[1];
etc......

ou encore

$output = str:0x02, len:0x04, cmd:0x08, dt1:1,dt2:1, dt3:1,end:0x03 ;
parse_str($str, $output);
echo $output['str:']; // 0x02
echo $output['len:'][0]; // 0x04
echo $output['cmd:'][1]; // 0x08
etc...

fwrite($fp, "{ \"str\":0x02, \"len\":0x04, \"cmd\":0x03, \"dt1\":1, \"dt2\":1, \"dt3\":1, \"end\":0x03  }" );

ca ne veut pas marcher.

L'arduino recoit bien une info mais ne la décode pas.
Voici le code de l'arduino

char c;
void setup() 
{
    pinMode(8, OUTPUT);
   Serial.begin(9600);
 }
void loop() 
{
     if (Serial.available() > 0) 
       {  
         uint8_t lengthData = Serial.available();
         //digitalWrite(8,HIGH);
        char data[lengthData];
           int j = 0;
           String affi="";
           while(Serial.available())
           {
            // digitalWrite(8,HIGH);          // pour debug  fonctionne
                  c = Serial.read();
                  affi+=c;
                  j=j+1;
                  
                      switch (j) 
                             {
                                case 5:
                                data[0]=c;                 
                                break;
                                case 11:
                                data[1]=c;                 
                                break;
                                case 17:
                                data[2]=c;                 
                                break;
                                case 23:
                                data[3]=c;                 
                                break;
                                case 29:
                                data[4]=c;                 
                                break;
                                case 35:
                                data[5]=c;                 
                                break;
                                case 41:
                                data[6]=c;                 
                                break;                            
                              }}

              if(!Serial.available())
              { 
               if (data[0]== '2')
                 
               { digitalWrite(8,HIGH);           // pour debug  ne fonctionne  pas
               } 
                if(data[0]== '2' && data[6]=='3')
	     { 
                 
                  switch (data[2]) {
                                     case '3':
                                     if (data[4]=='1')
                                     {
                                     
                                          switch (data[3]) {
                                                             case '1':                                        
                                                                   //digitalWrite(8,HIGH);
                                                                   break;
                                                              case '2':
                                                                    digitalWrite(8,LOW);
                                                                    break;
                                                          
                                          }
                                          
                                      
	                             }
                              
                                   }  
                               }  
         } 
       }
}

une petite suggestion ??

J'ai essayé plusieur chose dont en autre phpserial class mais je n'arrive pas coté arduino a décoder mon msg json et a récupérer les infos utiles..

Pour l'instant je vais donc rester l'ethernet shield branché sur l'arduino...
Merci quand même..