En C++ vous ne pouvez pas concatener une chaine constante et un buffer générique. vous pourriez concatener 2 Strings avec un S majuscule (la classe String) mais on vous déconseillera fortement de l'utiliser, préférez les fonctions qui restent proches de la mémoire et du C
Effectuez le write en deux temps, un write de la commande et un write du payload ou alors mettez au début de la structure 5 chars de plus initialisés avec AT$SF=
et Le payload sera complet
Pour mettre des bouts d'octets dans des endroits particuliers il suffit d'utiliser les fonctions qui traitent les bits
Mais bon - je répondais à votre question théorique - AT$SF= n'attends pas un buffer binaire mais chaque octet doit être représenté en hexadécimal sur 2 caractères (0xA
doit être écrit comme 0A
pas juste A
) - on passe une chaine en codage ASCII
AT$SF=00112233445566778899aabb
Il faudra donc utiliser un print en HEX de chacun des constituants (en faisant attention de bien mettre le caractère '0' devant les valeurs inférieures à 0xF pour que ce soit sur 2 caractères) une fois que vous avez bâti le payload. Utiliser une union avec la struct ci dessus et un tableau de 12 octets simplifiera cela.
Essayez de regarder ce code:
typedef struct rowPayload_s {
uint8_t id;
int16_t temperature;
uint16_t humidity;
uint16_t poids; // pas terrible de mélanger français et anglais dans les noms des champs, faites un choix
uint16_t in; // pas très parlant comme nom de variable
uint16_t out; // pas très parlant comme nom de variable
uint8_t vba; // pas très parlant comme nom de variable
};
union payload_u
{
rowPayload_s data;
uint8_t rawData[sizeof(rowPayload_s)];
} payload;
void setup() {
Serial.begin(115200);
Serial.print(F("taille de la structure = "));
Serial.print(sizeof(rowPayload_s));
Serial.println(F(" octets"));
Serial.print(F("taille de l'union = "));
Serial.print(sizeof(payload));
Serial.println(F(" octets\n"));
// on initialise avec des valeurs reconnnaissables
payload.data.id = 0x00;
payload.data.temperature = 0x2211;
payload.data.humidity = 0x4433;
payload.data.poids = 0x6655;
payload.data.in = 0x8877;
payload.data.out = 0xaa99;
payload.data.vba = 0xbb;
Serial.print("AT$SF=");
// l'architecture étant little endian, l'octet de poids faible
// des valeurs sur 2 octets est en mémoire avant celui de poids fort
// une valeur 0x1234 sera représentée en mémoire par
// un octet à 0x34 suivi d'un octet à 0x12
// cf https://fr.wikipedia.org/wiki/Endianness#Little_endian
for (byte i = 0; i < sizeof(payload); i++) {
if (payload.rawData[i] <= 0xF) Serial.print("0"); // pour bien avoir 2 caractères
Serial.print(payload.rawData[i], HEX);
}
Serial.println();
}
void loop() {}
il affichera dans la console
```
taille de la structure = 12 octets
taille de l'union = 12 octets
AT$SF=00112233445566778899AABB
```
attention à l'ordre d'émission des octets, votre arduino est petit-boutiste (mot de poids faible en tête), si vous recevez cela dans une structure côté serveur qui serait gros-boutistes (mot de poids fort en tête) ça ne fonctionnera pas pour les données sur 16 bits, il faudra inverser des octets à la lecture (ou les émettre dans bon sens)

(source wikipedia)
il est a noter que la norme C ou C++ ne définit pas exactement le comportement d'une structure et d'une union et ne garantit pas que les octets seront agencés dans l'ordre de déclaration de la structure, que le compilateur peut faire des optimisations etc. la seule chose qui est garantie c'est que si vous avez utilisé un membre de l'union pour écrire, vous êtes sûr de pouvoir relire avec ce même membre. Dans la pratique cependant la majorité des compilateurs se comportent comme attendu, et donc vous retrouvez dans le tableau de 12 octets la représentation mémoire de la structure telle que déclarée.