Receive a Transmit Status in Arduino with Xbee

Hi friends

Part of the operation of the system that I am doing, is that it knows that the data that I send through the frames already established by the API mode was successfully received by the Xbee on the PC or on the other hand that it was not received.
That is why I rely on the Transmit Status plot that Xbee already provides and that I can see in the XCTU.

I am going to show the example with the sending of a frame from the PC and the reception of the Transmit Status, it is only to illustrate, because in reality the sending comes from the sensor and the reception of the Transmit Status is for the sensor. Well let's get started. The following image we can see a frame that was sent and a frame that was received, the frame that was received is the Transmit Status, this frame, as I told you at the beginning, indicates if the frame was received or if it was not received.

We can observe the HEX composition of the frame in bytes.

Transmit Status (API 1)

7E 00 07 8B 01 FF FE 00 00 00 76

Start delimiter: 7E
Length: 00 07 (7)
Frame type: 8B (Transmit Status)
Frame ID: 01 (1)
16-bit dest. address: FF FE
Tx. retry count: 00 (0)
Delivery status: 00 (Success)
Discovery status: 00 (No discovery overhead)
Checksum: 76

Now I disconnect the power from the Arduino, simulating that the Xbee ran out of power and I send the plot again to see the result of the Transmit Status.

Transmit Status (API 1)

7E 00 07 8B 01 FF FE 02 25 02 4D

Start delimiter: 7E
Length: 00 07 (7)
Frame type: 8B (Transmit Status)
Frame ID: 01 (1)
16-bit dest. address: FF FE
Tx. retry count: 02 (2)
Delivery status: 25 (Route not found)
Discovery status: 02 (Route discovery)
Checksum: 4D

We can already see the differences between a Plot that indicates a successful package delivery and a failed delivery.

What I did was grab an example of TX from the Andrewrapp library and copy it into my code, which should work. But it doesn't work and I don't know why.

I also thought that since I already knew how Transmit Status is composed, I could just add it to the code and compare it with an incoming frame and be able to decide if it is the same or if it is different.

Below is the code I am working with. You will see a lot of comments, since I am adding other stages such as the Datalogger, which will work once I manage to develop this problem that I have. My idea is to save the data frame in case the message was not delivered, this to keep a record of the measurements, and send them back to the beginning of the code trying to send them again. I can also hear observations in this part.

Finally, you will also see the ADC stage commented, since I will also add within the frame where I am going to send the time and date, a voltage value, taken from a sensor.

//Librerias
#include <XBee.h>
#include <SafeString.h>
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <SoftwareSerial.h>
//#include <SPI.h> 
//#include <SD.h>

//DataLogeer
//const int chipSelect = 4;

//Xbee
SoftwareSerial xbeee(2, 3); //(Rx, TX)

XBee xbee = XBee();
ZBTxStatusResponse txStatus = ZBTxStatusResponse();

//ADC
//ADC--> const int ADC = A0;
//float voltPanel;
//TRAMAS
byte packet1[] = {0x7E, 0x00, 0x21}; //Byte delimitador y Longitud de trama // variar por el voltaje
byte packet2[] = {0x10, 0x01, 0x00, 0x13, 0xA2, 0x00, 0x41, 0x4E, 0xF1, 0x24, 0xFF, 0xFE, 0x00, 0x00,}; //Id de trama, tipo de trama, direccion de 64bits, opciones y numero de brincos.
// 00:11:46 05/01/2021 == 19 chars
byte fullPacket[3 + 14 + 19 + 1];// (Delimitador + longitud )+ (tipo + direccion)+ voltage + fecha + checksum = 37
                                //  [3 + 14 + 4 + 19 + 1]
char buffer [25]; // 19 la fecha  +1  '\0', 25 bytes de tamaño // cambiar porque hay voltaje
#define DEBUG SafeString::Output

//Setup
void setup() {
  Serial.begin(9600);
  delay(100);
  xbeee.begin(9600);
  xbee.setSerial(Serial);
  delay(100);
 // if (!SD.begin(4)) {
   // Serial.println("initialization failed!");
    //while (1);
  //}
  //Serial.println("initialization done.");
  delay(2000);
  Serial.println();
  Serial.println("MACHOTE DEL CODIGO PRINCIPAL");
  Serial.println("-------------------");

  SafeString::setOutput(Serial);
  }

void loop() {
  //while xbee.read();{ //Generar un loop que pregunte Se ha recibido un mensaje de la PC? 
    //SI-->proceder if myserial.read();
    //Verificar si hay Tramas en memoria
    //File dataFile = SD.open("MedicionesVoltPanel.txt");
    //SI--> enviar tramas una por una.
    //if (dataFile) {
      //read from the file until there's nothing else in it:
      //while (dataFile.available()) {
      //xbeee.write(dataFile.read());} //Enviar lo que va leyendo 
    //close the file:
    //dataFile.close();
    
    //Comprobar que hay SUCCESS en el Transmit STATUS
    //if (xbee1.readPacket(500)) {
    // got a response!
    // should be a znet tx status              
    //if (xbee1.getResponse().getApiId() == ZB_TX_STATUS_RESPONSE) {
      //xbee1.getResponse().getZBTxStatusResponse(txStatus);
      // get the delivery status, the fifth byte
      //if (txStatus.getDeliveryStatus() == SUCCESS) {
        // success.  time to celebrate
        //Serial.println("SUCCESS"));
      //} else {
        // the remote XBee did not receive our packet. is it powered on?
        //Serial.println("FAIL"));
      //}
    //}
  //} else if (xbee1.getResponse().isError()) {
    //Serial.println("ERROR"));
  //} else {
    // local XBee did not provide a timely TX Status Response -- should not happen
   //Serial.println("ERROR"));
  //}
       //SI-->Borrar datos de memoria
       //SD.remove(dataFile);
    //else
       //No-->Continuar con la lectura del nuevo dato
    //} else {   
    //No-->Continuar con la lectura del nuevo dato
    //} 

  tmElements_t tm;
  if (RTC.read(tm)) {
    sprintf(buffer, ",%02d:%02d:%02d,%02d/%02d/%04d", tm.Hour , tm.Minute, tm.Second, tm.Day, tm.Month, tmYearToCalendar(tm.Year));
    Serial.println(buffer); // con este print compruebo que la fecha y hora

    //Extraer Voltaje de ADC
    //Convertir voltaje a Valor REAL
    //voltPanel= ((float(analogRead(ADC))*5.0/1023)*3+25, 2);  //Aqui multiplico por 5 y divido por 1023, 
    //para tener el voltaje que lee el ADC y multiplo por 3 y umo 25, para dar el voltaje real.
    //convertir voltPanel a HEX 
    //Ingresar este valor a los datos, parte de la horayfecha (xx.xx,00:11:46,05/01/2021)
    
    //Actualizar length y las tramas de arriba.
    //{0x7E, 0x00, 0x27}; //0x27 19 caracteres de fecha + 4bytes del flotante + espacio
    
    // build fullpacket
    size_t idx = 0;
    memmove(fullPacket + idx, packet1, sizeof(packet1));
    idx += sizeof(packet1);
    memmove(fullPacket + idx, packet2, sizeof(packet2));
    idx += sizeof(packet2);
    if ((idx + 19 + 1) > sizeof(fullPacket)) {
      // Si el tamaño es incorrecto
      Serial.println(F("fullPacket size wrong"));
    }
    
    memmove(fullPacket + idx, buffer, 19);
    idx += 19;
    // dejar un byte para el cheksum
    if ((idx + 1) != sizeof(fullPacket)) {
      // fullPacket size wrong
      Serial.println(F("fullPacket size wrong"));
    }

    int chksum = 0;
    for (size_t i = 3; i < idx; i++) { // comienza despues del tamaño dela trama
      chksum += fullPacket[i]; // comienza a sumar 
    }
    chksum = (0xff & chksum);
    chksum = (0xff) & (0xff - chksum);
    fullPacket[idx] = chksum;
    idx++; // El tamao total de la trama
    if (idx != sizeof(fullPacket)) {
      Serial.println(F("fullPacket size error"));
    }

    // Imprime el paquete
    size_t printSize = idx * 3; // ..<space>
    cSF(sfPacket, printSize);
    for (size_t i = 0; i < idx; i++) {
      //sfPacket += "0x";
      if (fullPacket[i] < 16) {
        sfPacket += '0'; 
      }
      sfPacket.print(fullPacket[i], HEX); 
      sfPacket.print(' ');
    }
    Serial.println(sfPacket);

    xbeee.write (fullPacket , idx);   
    delay(10000);

    //Comprobar que el mensaje fue enviado, Programar un analisis de la Trama API Transmit Status 
    //Comprobar si dice SUCCESS
      //Si-->Volver a iniciar el ciclo.
    //Comprobar que hay SUCCESS en el Transmit STATUS
    if (xbee.readPacket(500)) {
      if (xbee.getResponse().getApiId() == ZB_TX_STATUS_RESPONSE) {
        xbee.getResponse().getZBTxStatusResponse(txStatus);
      // get the delivery status, the fifth byte
        if (txStatus.getDeliveryStatus() == SUCCESS) {
          Serial.println("SUCCESS");
        } else {
        // the remote XBee did not receive our packet. is it powered on?
          Serial.println("FAIL");
      }
    //}
  //} else if (xbee1.getResponse().isError()) {
    //Serial.println("ERROR"));
  //} else {
    // local XBee did not provide a timely TX Status Response -- should not happen
   //Serial.println("ERROR"));
  //}  
      //No-->Ir al Datalogger 
      //File dataFile = SD.open("MedicionesVoltPanel.txt", FILE_WRITE);// open the file.
         //Activar el Datalogger Guardar la Trama que se intento enviar
         //if (dataFile) {
         //dataFile.println(fullPacket);
         //Cerrar Datalogger
         //dataFile.close(); }      
  }
}
  }
}   
void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}