bonjour je n'arrive pas a trouver ou je fais l'erreur de raisonnement
voici le bout de code :
void parse_command()
{
char * pch;
int ii = 0;
//parsing et Identification des attributs
pch = strtok (command_line,"|");
while (pch != NULL)
{
sprintf(arg_list[ii],"%s", pch);
pch = strtok (NULL, "|");
Serial.println(arg_list[ii]);
ii++;
}
//identification de l'ID
Command_ID = -1;
for (ii=0; ii<NB_COMMANDS; ii++)
{
if (strcmp(Command_List[ii], arg_list[0]) == 0)
{
Command_ID = ii;
Serial.println("ok commande");
break;
}
}
}
si je tape la console répond :
CmdCfg
ok commande
CmdCfg
Command executée : CmdCfg->done
si je tape <CmdCfg|52|23> la console répond :
CmdCfg
52
23
Unknown Command -> CmdCfg
la chaine est parsée la commande semble correcte mais le code n'est pas reconnu j'ai posé des serialprint pour tracer et que j’enlèverai ...
pour résumer dans un cas CmdCfg est reconnu lorsqu'il est seul
CmdCfg n'est pas reconnu avec plusieurs valeurs alors que c'est bien la même chaine qui est affichée
je soupçonne un probléme de fin de chaine genre caractère zéro mais je vois pas comment modifier.
je veux bien poster les autres bout de code mais a partir du moment ou
mon ID de commande n'est pas détecté le reste est pas vraiment utile..
généralement le diable se cache dans les détails... vous ne pourriez pas poster un code complet, qui compile, qui permet de saisir le commande sur la console série et qui montrerait le problème que vous rencontrez ?
if (index < MAX_CMD_LEN) command_line[index++] = incomingByte;
même résultat je regarde ca plus avant des que possible j'ai des invités et ma femme rale un peu
merci
votre femme a raison ! Elle devrait râler plus, c'est la Journée Internationale des Femmes en plus !!!
Après le départ des invités et avoir fait la vaisselle, le ménage le repassage et le repas du soir , regardez mon code et en quoi il diffère du votre... vous avez peut-être un débordement mémoire quelque part…
Tu devrais définir ta fonction parse non pas comme void the mais comme bool et renvoyer un true si la commande a été correctement parsée et un false sinon, que tu pourrais tester juste après l'appel.
De plus, pour déboguer, tu devrais afficher la valeur de ii lorsque tu affiches arg_list[ii]
Cette liste occupe 10 fois plus de place que la commande elle-même.
Les variables globales utilisent 953 octets (46%) de mémoire dynamique, ce qui laisse 1095 octets pour les variables locales. Le maximum est de 2048 octets.
Les arguments n'ont pas besoin d'être recopiés dans une liste, les adresses suffisent. La liste devient une liste de pointeurs.
Les variables globales utilisent 333 octets (16%) de mémoire dynamique, ce qui laisse 1715 octets pour les variables locales. Le maximum est de 2048 octets.
Et hop : 620 octets économisés, et le fonctionnement est identique.
hbachetti:
Juste une remarque à propos de la liste d'arguments :
vu son demi bout de code je pense qu’il veut peut être garder une copie indépendante du buffer d’entrée qui peut se ré-remplir dans la loop s’il y a des trucs qui tournent en machine à état par exemple... dans ce cadre je ne voulais pas juste garder les pointeurs.
De plus j’ai Un doute aussi sur l’origine de son bug, s’il a pris des pointeurs seulement sans réserver d’espace et fait son sprintf (au lieu de strcpy pour gâcher encore plus de mémoire ) alors il a un souci là et je voulais qu’il regarde cette partie
Mais Oui dans l’absolu il faudrait une taille adaptée pour chaque paramètre j’ai fait ça à l’arrache avec la constante que j’avais sous la main Sans m’ennuyer, c'était pour tester le parser
vu son demi bout de code je pense qu'il veut peut être garder une copie indépendante du buffer d'entrée qui peut se ré-remplir dans la loop s'il y a des trucs qui tournent en machine à état par exemple... dans ce cadre je ne voulais pas juste garder les pointeurs.
Oui mais le problème est que strtok() place des ZÉRO à la place des séparateurs, donc la commande est perdue de toutes façons.
hbachetti:
C'est l'inconvénient d'un code incomplet
Oui mais le problème est que strtok() place des ZÉRO à la place des séparateurs, donc la commande est perdue de toutes façons.
oui mais une fois le parsing fait elle est réutilisée par son code d'attente de commande
case '<':
commandIndex = 0;
memset(command_line, 0, sizeof(command_line));
break;
vu que Serial est asynchrone, je me disais qu'il reçoit une commande, ça tourne un moment avec les paramètres reçus jusqu'à la réception de la prochaine commande. il faut donc bien un buffer séparé pour les paramètres en cours et ceux qui arrivent ensuite.
mais pure spéculation, si ça se trouve il exécute la commande sur place et tout est synchrone, auquel cas oui, autant garder une liste de pointeurs dans le buffer série (et c'est pour cela que strtok met des 0 sur les séparateurs)
alors code complet bah y a 11 unités avec du code qui n'a strictement rien a voir
donc je donne le code de l'unité parseur
#include "Arduino.h"
#include "configvariable.h"
#include "parseur.h"
/*DETECTION ET DECOMPOSITION D'UNE COMMANDE*/
#define NB_COMMANDS 5 // nombre de commandes
#define MAX_ARGS 15 // nombre maximum d'arguments d'une commande
#define MAX_CMD_LEN 80
#define MAX_ARGS_LEN 4
//Déclaration de la liste des identifiants commandes.
enum Command_IDs {
CmdCfg = 0,
CmdEnr = 1,
CmdSim = 2,
DemCfg = 3,
DemVer = 4
};
//Syntaxe des commandes
char* Command_List[NB_COMMANDS] = {
"CmdCfg",
"CmdEnr",
"CmdSim",
"DemCfg",
"DemVer"
};
//Reception commande
int Command_ID;
char arg_list[MAX_ARGS][MAX_ARGS_LEN];
char incomingByte;
int index;
char command_line[MAX_CMD_LEN];
int iPrintConfirmation;
void lireCommande(){
if (Serial.available()) {
incomingByte = Serial.read();
//Serial.println(incomingByte);
switch (incomingByte)
{
case '<':
index = 0;
memset(command_line, 0, MAX_CMD_LEN - 1);
break;
case '>':
command_line[index+1] = 0;
parse_command();
exec_command();
break;
default :
if (index < MAX_CMD_LEN) command_line[index++] = incomingByte;
}
}
}
//Accusé de reception commande
void ack_command(char *message)
{
iPrintConfirmation =1;
if (iPrintConfirmation>0)
{
Serial.print("Command executée : ");
Serial.print(Command_List[Command_ID]);
Serial.print("->");
Serial.print(message);
Serial.println();
}
}
//execution des commandes
void exec_command()
{
switch (Command_ID)
{
case CmdCfg:
Serial.println("CmdCfg");
ack_command("done");
break;
case CmdEnr:
Serial.println("CmdEnr");
ack_command("done");
break;
case CmdSim:
Serial.println("CmdSim");
ack_command("done");
break;
case DemCfg:
Serial.println("DemCfg");
ack_command("done");
break;
case DemVer:
Serial.println("DemVer");
ack_command("done");
break;
default :
Serial.print("Unknown Command -> ");
Serial.println(command_line);
}
}
//Parsing identifiant commande et arguments
void parse_command()
{
char * pch;
int ii = 0;
//parsing et Identification des attributs
pch = strtok (command_line,"X");
while (pch != NULL)
{
sprintf(arg_list[ii],"%s", pch);
pch = strtok (NULL, "X");
Serial.println(arg_list[ii]);
ii++;
}
//identification de l'ID
Command_ID = -1;
for (ii=0; ii<NB_COMMANDS; ii++)
{
if (strcmp(Command_List[ii], arg_list[0]) == 0)
{
Command_ID = ii;
Serial.println("ok commande");
break;
}
}
}
le code du .h
/*
DETECTION ET DECOMPOSITION D'UNE COMMANDE
*/
#include <stdlib.h>
#include <string.h>
void lireCommande();
//Accusé de reception commande
void ack_command(char *message);
//This function execute a command. Amend this function with your own commands
void exec_command();
//Parsing identifiant commande et arguments
void parse_command();
je sais que je dois avoir des gros voir tres gros progrès a faire dans la structuration du code en unités et dans les includes vu les problèmes de compilation parfois avec des déclarations repetitive ou les variables inconnues car non déclarées
je m'en sors toujours avec des solutions de bric et de broc
j'ai lu relu et rerelu l'organisation d'un programme vec la décomposition en unité et avec les .h et les includes mais j'ai toujours autant de mal a savoir ou mettre telle et telle procédure ou telle déclarations
mais ca c'est un autre probléme
Après a dire vrai toute cette partie de code je l'avais faites avec des Strings et ca fonctionnait sans problème .... j'ai voulu jouer au gros bras en utilisant des char mais peut etre je suis pas de taille ...
de même par conséquent les fonctions sprintf strcpy etc .... pfiou ....