Intégrer facilement des valeurs dans un libellé texte

Bonjour à tous,

J'ai trouvé pas mal de ressources sur ce forum à ce sujet mais rien qui réponde directement à la question que je me pose.

Je voudrais savoir s'il est possible (facilement) d'intégrer des valeurs (int ou float) dans un libellé texte qu'on passe en entrée d'une fonction. Y a t'il une ruse de coyote ou doit-on systématiquement jongler avec le sprintf ?

Je vous pose le contexte. J'ai deux cartes, une méga (centrale) et une uno+W5500 (connecter), les deux discutent en UART.

En temps normal, le connecter envoi périodiquement un octet de ping à la centrale pour signaler qu'il est toujours vivant, et la centrale lui envoi une trame toute les 5 minutes contenant les données des différents capteurs qui sont branchés dessus. Lorsque le connecter reçoit la trame, il exécute une requête GET sur un serveur que j'ai en ligne sur le net qui va stocker les valeurs dans une DB.

Je suis en train d'ajouter une fonctionnalité d'alerte, c'est à dire que si l'une des valeurs de température (par exemple) lue par la centrale dépasse un seuil prédéfini, la centrale doit envoyer une trame spécifique au connecter qui contient un message d'alerte. Le serveur Web recevant cette alerte, envoi immédiatement un email contenant le message. Pour signaler au connecter qu'il va recevoir une alerte et non une mesure, je fais précéder la trame par un octet valant 17.

Dans le code de ma centrale:

sensor_value[INDEX_TEMP_SYSTEM] = bme.readTemperature();
if (sensor_value[INDEX_TEMP_SYSTEM] >= thresold_high_system) {
  sendAlert2Connecter("Surchauffe système","Une surchauffe du systeme a été détectée !");
}

Contenu de la fonction sendAlert2Connecter et déclaration du alert_connecter:

DynamicJsonDocument alert_connecter(300);   // Preparation du JSON pour communication serie

void sendAlert2Connecter(char* type, char* message) {
	if (connecter_connected){		
		Serial.println("[UART2] Envoi d'une alerte immédiate...");
		ledUART(0,2,false,HIGH);
		Serial2.write(17); // Octet d'identification
		idleTime(300);
		alert_connecter.clear();
		/* Trame de communication Centrale -> Connecter */
		alert_connecter["emitter_key"] 	= EMITTER_KEY;
		alert_connecter["type"] 		= type;
		alert_connecter["message"] 	= message;

		serializeJson(alert_connecter, Serial2);
		serializeJson(alert_connecter, Serial);
		Serial.println("");
		sayBip(440,100);
		idleTime(100);
		sayBip(440,100);
		ledUART(0,2,false,LOW);
	}
}

Donc dans mon exemple, quelle serait la méthode la plus simple pour intégrer directement le contenu de sensor_value[INDEX_TEMP_SYSTEM] dans mon message à l'appel de la fonction sendAlert2Connecter ?
(genre sendAlert2Connecter("Surchauffe système","Une surchauffe du systeme a été détectée ${sensor_value[INDEX_TEMP_SYSTEM]}°C !"):wink:

Je sais pas si je suis bien clair... dites moi si vous comprenez pas ce que je veux dire :smiley:

Salut,
Essaie quelque chose du style :

int temperature = 27;

// tu convertis déja ça en un string
String convertion_temperature = String(temperature);

// ensuite tu assembles le tout avec un simple +
String envoi = "Une surchauffe a été détectée de " + convertion_temperature + " °C"

En quoi l'utilisation du sprintf vous gêne t'elle ? Perso, je trouve que vous auriez bien tort de remplacer par des concaténation de strings, qui vont transformer votre tas en gruyère.

Pas faux, même sur une MEGA.
Illustration : arduino-la-fragmentation-memoire

Merci @mskna17, j'avais pas trop essayé de passer par une String car souvent décriée, mais je vais essayer et voir l'impact mémoire que ça a sur mon code.

@JiPe38 @hbachetti effectivement vous avez raison, la gestion de la mémoire serait loin d'être optimale avec une String (une Mega n'excuse pas tout). Ce n'est pas que le sprintf me gène particulièrement, mais je me demandais s'il y avait un autre moyen, joli et rapide à écrire, et pas catastrophique niveau mémoire pour faire ce genre de chose proprement.

La possibilité de réserver un certain nombre d'octets (comme d'ailleurs très bien expliqué dans le tuto de hbachetti) permettrait d'éviter les problèmes dans le cas précis de ce projet. En effet, si la taille maxi de la phrase est parfaitement connue dés le départ:
Exemple donné par mskna17: "Une surchauffe a été détectée de " + convertion_temperature + " °C".

Tu déclares
String Surchauffe;
Surchauffe.reserve(50); // la phrase ne dépassera jamais cette taille

C'est donc uniquement en connaissance de cause que tu pourras utliliser la classe String, dans les autres cas il faudra s'en passer.

Merci @ard_newbie, je ne connaissais pas cette méthode des Strings. Effectivement la taille maximale du message peut être connue car je sais d'avance quels types d'alerte la centrale est capable d'envoyer. Je vais essayer ça.

Ce que l'on définit avec reserve(), ce n'est pas la taille maximale de la String, elle continuera à grandir si vous allouez plus de texte que la valeur réservée, mais si vous ne dépassez pas la taille allouée, alors il n'y aura pas d'allocation dynamique.

Ensuite il ne faut pas utiliser + pour concaténer, ça génère des Strings intermédiaires. Il faut le faire en plusieurs fois avec += ou utiliser concat.

Ok merci @J-M-L, donc il n'y a pas vraiment de solution miracle pour "économiser" des lignes de codes. Soit utiliser sprintf, soit concat.

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