Go Down

Topic: Arduino Uno W5100 et Domoticz (Read 858 times) previous topic - next topic

manubis_sanchez

Pas de problème.

Si jamais certains voient des améliorations, optimisation ou contrôles d'erreurs pour ce bout de code, je suis preneur.

J4l13n

#46
Aug 17, 2019, 12:21 pm Last Edit: Aug 17, 2019, 12:22 pm by J4l13n
domoticz renvoie
Code: [Select]
{
   "status" : "OK",
   "title" : "Update Device"
}


Peut être extraire le "OK" pour confirmé la bonne réception et  renvoyer  la syntaxe le cas contraire.

J'essayerais demain étant au taf...

@+
while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

supercc

#47
Aug 17, 2019, 12:54 pm Last Edit: Aug 17, 2019, 01:13 pm by supercc
Quote
Si jamais certains voient des améliorations, optimisation ou contrôles d'erreurs pour ce bout de code, je suis preneur.
Puisque tu demandes ;-)

Il faudrait utiliser la variable serveur dans la ligne :

client.println("Host: 192.168.1.xx"); // IP du serveur Domoticz

Le message envoyé par client.println("Connexion terminée"); n'est pas dans la norme HTTP ;-) je pense que tu peux le virer.

Quel est le rôle de delay(1) après l'émission de la requête. Si c'est pour laisser le temps au serveur de répondre qu'est ce qui garanti qu'il répondra dans ce temps ?


Sinon si tu es motivé, construire la fonction générale (pas testé ni même compilée):

Code: [Select]


int domoticzSend(char *server,  unsigned short port, unsigned idx, char *value) {

   char msg[100]="GET /json.htm?type=command&param=udevice&idx=";
   char *p=msg+strlen(msg);
   sprintf(p,"%d&nvalue=0&svalue=%s HTTP/1.1\nHost: %s\n\n", idx,  value, server);

  if (client.connect(server, port)) {
      Serial.println("Connecté au serveur");
      client.print(p);
  }
  //...
}



Et puisqu'on y est une compilation conditionnelle pour spécifier l'utilisation de EthernetClient ou de WifiClient, que cette fonction soit portable sur tous les arduinos shield Ethernet, esp8266, ....

Histoire que ta requête soit réglée en une ligne (à condition d'avoir dans value la représentation chaîne de caractères de ce que tu veux fixer dans svalue).

domoticzSend("192.168.1.xx",  port,  63,  value);

et celle de J4l13n :

domoticzSend("192.168.1.200", 8080, 1, "22.33");

Quand ça marche tu déposes le code sur github (ou autre forge à accès anonyme), merci d'avance ;-).

Blague à part je pense que ce genre de fonction éviterai des galères. Marre de toujours réinventer la roue ;-)

Mais peut-être existe-elle déjà ?


J4l13n




Code: ("Quote from: supercc Sat Aug 17 2019 12:54:17 GMT+0200 (heure d'été d'Europe centrale)") [Select]


domoticzSend("192.168.1.xx",  port,  63,  value);

et celle de J4l13n :

domoticzSend("192.168.1.200", 8080, 1, "22.33");


La c'est un exemple avec seulement une variable pour 1 produit, mais on peut envoyer la T° et Humidité :

Code: [Select]
domoticzSend("server", port, id, value1, value2);

@+
while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

supercc

Dans ce cas comment s'écrit la requête (GET /json.htm?type=command&param=udevice&idx=....) ? Et avec 3 arguments ? histoire de voir quelle boucle faire...

manubis_sanchez

Quote
Il faudrait utiliser la variable serveur dans la ligne :

client.println("Host: 192.168.1.xx"); // IP du serveur Domoticz
Yes, aucun soucis.

Quote
Le message envoyé par client.println("Connexion terminée"); n'est pas dans la norme HTTP ;-) je pense que tu peux le virer.
Du coup, je viens de me rendre compte que je n'aurai pas dû forcément tout traduire. La ligne originale était "client.println("Connection: close");"

Quote
Quel est le rôle de delay(1) après l'émission de la requête. Si c'est pour laisser le temps au serveur de répondre qu'est ce qui garanti qu'il répondra dans ce temps ?
Ça, ça fait partie des bouts de codes que j'ai trouvé. S'il n'est pas nécessaire, autant l'enlever ;)

Sinon, pour ta fonction, je veux bien la tester la semaine prochaine. Là, je profite de mon installation fonctionnelle pour calibrer un peu la formule de la température.
Je vais me replonger un peu dans le C++ pour comprendre ton code (surtout les pointeurs), je ne suis pas développeur mais ça m'intéresse énormément de participer à ce genre de projet. Je ne peux qu'apprendre.
Il ne me semble pas qu'une telle fonction existe vu le temps que j'ai passé à la chercher. Ou alors, elle est mal répertoriée...

J4l13n

Dans ce cas comment s'écrit la requête (GET /json.htm?type=command&param=udevice&idx=....) ? Et avec 3 arguments ? histoire de voir quelle boucle faire...
Une avec 3 valeurs:
https://www.domoticz.com/wiki/Domoticz_API/JSON_URL's#Temperature.2Fhumidity.2Fbarometer
Code: [Select]
/json.htm?type=command&param=udevice&idx=IDX&nvalue=0&svalue=TEMP;HUM;HUM_STAT;BAR;BAR_FOR


@+
while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

J4l13n

Yes, aucun soucis.

Du coup, je viens de me rendre compte que je n'aurai pas dû forcément tout traduire. La ligne originale était "client.println("Connection: close");"

Ça, ça fait partie des bouts de codes que j'ai trouvé. S'il n'est pas nécessaire, autant l'enlever ;)

Sinon, pour ta fonction, je veux bien la tester la semaine prochaine. Là, je profite de mon installation fonctionnelle pour calibrer un peu la formule de la température.
Je vais me replonger un peu dans le C++ pour comprendre ton code (surtout les pointeurs), je ne suis pas développeur mais ça m'intéresse énormément de participer à ce genre de projet. Je ne peux qu'apprendre.
Il ne me semble pas qu'une telle fonction existe vu le temps que j'ai passé à la chercher. Ou alors, elle est mal répertoriée...
Code: [Select]
if (client.connect(server, 8080)) {
    Serial.println("connexion avec le serveur OK");
   // Make a HTTP request:
   client.print("GET /json.htm?type=command&param=udevice&idx=");
   client.print(2);
   client.print("&nvalue=0&svalue=");
   client.print(temperature);
   client.print(";");
   client.print(humidite);
   client.print(";");
   client.print("2");
   client.println(" HTTP/1.1");//
   client.println("Host: 192.168.1.200:8080");//
   client.println();
 } else {
   Serial.println("connection failed");
 }


Comme ça, ça fonctionne chez moi.
@+
while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

supercc

Je vais me replonger un peu dans le C++ pour comprendre ton code (surtout les pointeurs), je ne suis pas développeur mais ça m'intéresse énormément de participer à ce genre de projet. Je ne peux qu'apprendre.
Il ne me semble pas qu'une telle fonction existe vu le temps que j'ai passé à la chercher. Ou alors, elle est mal répertoriée...
En attendant, si J4l13n est dispo on aura peut être avancé... C'est peut- être aussi l'occasion de voir comment fonctionnent en C les fonctions à nombre variable d'arguments.




supercc

Voici la doc de l'API de domoticz utilisée.

D'après un parcours rapide des exemples :

Beaucoup de possibilités. Votre requête est de type command (type=command), il y a d'autres types de requêtes

Dans une requête de type "command", le nom de la commande est spécifiée dans le paramètre param. Dans votre cas la commande est udevice (user device ?).

Les commandes udevice acceptent toutes un idx. Mais en ce qui concerne les nvalue et les svalue c'est plus divers. Mais ce n'est pas grave, pour plus de souplesse il faut laisser l'utilisateur spécifier les 2 sous forme de chaîne de caractères. Donc pas de nombre variables d'arguments AMHA.

En ce qui concerne la valeur de retour pour la gestion d'une erreur du coté domoticz, d'après a doc, il faut en effet s'intéresser à la réponse et surtout à la ligne "status". Je ne pense pas que cela justifie l'utilisation d'une bibliothèque JSON, un simple appel à la fonction strstr() permettra de repérer les lignes "status" : "ERR". Du coup voici par exemple la valeur de retour possibles (type d'erreur).
  * 0 : tout ok
  * -1 : pb de connexion au serveur
  * -2 : pb lors de l'émission de la requête
  * -3 : pb lors de la réception (pas le ligne status)
  * -4 : pb : status=ERR


Compte tenu de ces éléments le prototype serai plus :

int domoticzUdeviceSet(char *server, unsigned short port, int idx, char *nvalue, char *svalue);


PS : si dans mon exemple j'utilise des tableaux de char, un pointeur sur char, sprintf c'est dans un but d'optimisation, histoire que la fonction ne joue pas avec le tas (String). Le tas est la zone mémoire réservée aux allocations dynamiques dont String est friande, mais la gestion de cette zone mémoire n'est pas efficace sur petite architecture (uno, nano, ...). Jouer avec les pointeurs c'est piégeux mais en général plus efficace (CPU, mémoire). D'ailleurs je viens de corriger le code de mon exemple (remplacer client.print(p) par client.print(msg)). A vous de voir ;-)


J4l13n

Salut j'ai eu pas mal de taf ..

pour info je suis passé sous Jeedom car  l'interface est  mieux a mon goût :)

Et les syntaxes d'envoient sont les mêmes, j'ais  donc mis 30s basculé le sketch.

Pour ton lien sur  les fonctions à nombre variable d'arguments  j'ai rien piger...
j'ai vu celui de zestedesavoir  mais il reprenne les mêmes syntaxes.

Sans exemple concret pour le newbie que je suis c'est pas facile...


@+
while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

supercc

Salut J4l13n,

Quote
Pour ton lien sur  les fonctions à nombre variable d'arguments  j'ai rien piger...
j'ai vu celui de zestedesavoir  mais il reprenne les mêmes syntaxes.

Sans exemple concret pour le newbie que je suis c'est pas facile...
Te biles pas, on n'en a normalement pas besoin d'après ce que je propose plus haut.

Quote
Donc pas de nombre variables d'arguments AMHA.
Donc maintenant ta carte envoie bien ses valeurs à domoticz ? Elle n'a jamais besoin d'en récupérer ?

J4l13n

Salut J4l13n,

Te biles pas, on n'en a normalement pas besoin d'après ce que je propose plus haut.

Donc maintenant ta carte envoie bien ses valeurs à domoticz ? Elle n'a jamais besoin d'en récupérer ?
Bonjour, 
ah ok ^^ j'ai chercher un peu ..
Oui ça fonctionne parfaitement, mais c'est JEEDOM maintenant , j'ai mis une condition pour n'envoyer que si les sondes on changer de valeur.
Je vais essayer d'allumer une led sur un UNO, https://blognote.jeremyblaizeau.com/faire-communiquer-jeedom-arduino-diy/
et je vais regarder aussi le MQTTque Charly26 avait proposer https://forum.arduino.cc/index.php?topic=631576.msg4276372#msg4276372
@+
while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

supercc


J4l13n

Bonjour,

j'essaye de transcrire ce que reçois l'Arduino UNO avec le shield W5100 avec ce code :
Code: [Select]
#include <SPI.h>       
#include <Ethernet.h>
#include <EthernetUdp.h>       

byte mac[] = { 0xDE, 0xBE, 0xAD, 0xEF, 0xFE, 0xE7 };
IPAddress ip(192, 168, 1, 203); // ip du shield Ethernet

unsigned int localPort = 8000;      //port local à écouter

// tableaux de caractères pour recevoir des données
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //caractères reçus
char  ReplyBuffer[] = "acknowledged";       // caractères à envoyer

EthernetUDP Udp;

void setup() {
Serial.begin(9600);
  Ethernet.begin(mac,ip); // initialisation du Shield Ethernet

  Udp.begin(localPort); // initialisation UDP
  Serial.println("fin setup");
  Serial.println(Ethernet.localIP());
  delay(5000);
//Ehernet
 
}

void loop() {
  //si des données sont disponibles, lire le paquet
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i =0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    //lit les données dans le tableau de réception
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // envoie une réponse au port et adresse qui l'a envoyé
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}


Mais quand je tape 192.168.1.203:8000/12345

J'ai rien qui s'affiche dans le terminal  à par le :

Code: [Select]
fin setup
192.168.1.203


Une idée ? merci 
while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

Go Up