// /***
//  *  This example shows LoRaWan protocol joining the network in OTAA mode, class A, region EU868.
//  *  Device will send uplink every 20 seconds.
// ***/

// #define OTAA_BAND (RAK_REGION_EU868)
// #define OTAA_PERIOD 20000
// #define  OTAA_DEVEUI   {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x0E, 0x49, 0x55} // {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x88} 
// #define  OTAA_APPEUI   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // {0x0E, 0x0D, 0x0D, 0x01, 0x0E, 0x01, 0x02, 0x0E}
// #define  OTAA_APPKEY   {0x8F, 0x29, 0xB7, 0xC3, 0xA4, 0x18, 0xBC, 0x2D, 0x7F, 0x16, 0xF8, 0xE2, 0x5E, 0x9C, 0x90, 0x00}//{0x8F, 0x29, 0xB7, 0xC3, 0xA4, 0x18, 0xBC, 0x2D, 0x7F, 0x16, 0xF8, 0xE2, 0x5E, 0x9C, 0x90, 0x00} // {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3E}

// /** Packet buffer for sending */
// uint8_t collected_data[64] = { 0 };

// void recvCallback(SERVICE_LORA_RECEIVE_T * data) {
//     if (data->BufferSize > 0) {
//         Serial.println("Something received!");
//         for (int i = 0; i < data->BufferSize; i++) {
//             Serial.printf("%x", data->Buffer[i]);
//         }
//         Serial.print("\r\n");
//     }
// }

// void joinCallback(int32_t status){
//     Serial.printf("Join status: %d\r\n", status);
// }

// /*************************************
//  * enum type for LoRa Event
//     RAK_LORAMAC_STATUS_OK = 0,
//     RAK_LORAMAC_STATUS_ERROR,
//     RAK_LORAMAC_STATUS_TX_TIMEOUT,
//     RAK_LORAMAC_STATUS_RX1_TIMEOUT,
//     RAK_LORAMAC_STATUS_RX2_TIMEOUT,
//     RAK_LORAMAC_STATUS_RX1_ERROR,
//     RAK_LORAMAC_STATUS_RX2_ERROR,
//     RAK_LORAMAC_STATUS_JOIN_FAIL,
//     RAK_LORAMAC_STATUS_DOWNLINK_REPEATED,
//     RAK_LORAMAC_STATUS_TX_DR_PAYLOAD_SIZE_ERROR,
//     RAK_LORAMAC_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS,
//     RAK_LORAMAC_STATUS_ADDRESS_FAIL,
//     RAK_LORAMAC_STATUS_MIC_FAIL,
//     RAK_LORAMAC_STATUS_MULTICAST_FAIL,
//     RAK_LORAMAC_STATUS_BEACON_LOCKED,
//     RAK_LORAMAC_STATUS_BEACON_LOST,
//     RAK_LORAMAC_STATUS_BEACON_NOT_FOUND,
//  *************************************/

// void sendCallback(int32_t status){
//     if (status == RAK_LORAMAC_STATUS_OK) {
//         Serial.println("Successfully sent");
//     } else {
//         Serial.println("Sending failed");
//     }
// }

// void setup() {

//     Serial.begin(115200, RAK_AT_MODE);
//     delay(2000);
  
//     Serial.println("RAKwireless LoRaWan OTAA Example");
//     Serial.println("------------------------------------------------------");
  
//     if(api.lorawan.nwm.get() != 1) {
//         Serial.printf("Set Node device work mode %s\r\n",
//             api.lorawan.nwm.set(1) ? "Success" : "Fail");
//         api.system.reboot();
//     }

    
//     uint8_t node_device_eui[8] = OTAA_DEVEUI; // OTAA Device EUI MSB first
//     uint8_t node_app_eui[8] = OTAA_APPEUI ;// OTAA Application EUI MSB first
//     uint8_t node_app_key[16] = OTAA_APPKEY; // OTAA Application Key MSB first

//     /* Configure LoRaWan Keys */

//     if (!api.lorawan.band.set(4)) {                                       // If the OTAA freqquency band setting is a failure, 
//         Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");                  // ... then we informe the user
//         return;                                                                       // ... and stop the program.
//     }    

//     if (!api.lorawan.deui.set(node_device_eui, 8)) {                               // If the DevEUI setting is a failure, 
//         Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");            // ... then we informe the user
//         return;                                                                       // ... and stop the program.
//     }    
//     if (!api.lorawan.appeui.set(node_app_eui, 8)) {                               // If the AppEUI setting is a failure, 
//         Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");       // ... then we informe the user
//         return;                                                                       // ... and stop the program.
//     }
//     if (!api.lorawan.appkey.set(node_app_key, 16)) {                               // If the AppKEY setting is a failure, 
//         Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");       // ... then we informe the user
//         return;                                                                       // ... and stop the program.
//     }

//     if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {                          // If we can't set LoRaWan Class to type A, 
//         Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");          // ... then we informe the user
//         return;                                                                       // ... and stop the program.
//     }
//     if (!api.lorawan.njm.set(RAK_LORA_OTAA)) {                                      // If we can't set the 'Network Join Mode' to OTAA
//         Serial.printf("LoRaWan OTAA - set network join mode is incorrect! \r\n");          // ... then we informe the user
//         return;                                                                       // ... and stop the program.
//     }

//     if (!api.lorawan.join()) {                                                      // If we didn't join the LoRa Network, ...
//         Serial.printf("LoRaWan OTAA - join fail! \r\n");                                // ... We informe the user
//         return;                                                                         // ... and stop the program.
//     }
  
//     /** Wait for Join success */
//     while (api.lorawan.njs.get() == 0) {                                            // While we don't join the Network, 
//         Serial.print("Wait for LoRaWAN join...");                                       // ... we informe the user
//         api.lorawan.join();                                                             // ... and try an other time
//         delay(10000);                                                                   // ... and wait 10 sec
//     }
  
//     if (!api.lorawan.adr.set(true)) {
//         Serial.printf("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
//         return;
//     }
//     if (!api.lorawan.rety.set(2)) {
//         Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
//         return;
//     }
//     if (!api.lorawan.cfm.set(1)) {
//         Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
//         return;
//     }
  
//     /** Check LoRaWan Status*/
//     Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF");	// Check Duty Cycle status
//     Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED");	// Check Confirm status
//     uint8_t assigned_dev_addr[4] = { 0 };
//     api.lorawan.daddr.get(assigned_dev_addr, 4);
//     Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]);	// Check Device Address
//     Serial.printf("Uplink period is %ums\r\n", OTAA_PERIOD);
//     Serial.println("");

//     api.lorawan.registerRecvCallback(recvCallback);
//     api.lorawan.registerJoinCallback(joinCallback);
//     api.lorawan.registerSendCallback(sendCallback);

//     pinMode( PA9, OUTPUT );

//     delay(10000);

// }

// void uplink_routine() {

//     /** Payload of Uplink */
//     uint8_t data_len = 0;
//     collected_data[data_len++] = (uint8_t) 't';
//     collected_data[data_len++] = (uint8_t) 'e';
//     collected_data[data_len++] = (uint8_t) 's';
//     collected_data[data_len++] = (uint8_t) 't';
  
//     Serial.println("Data Packet:");
//     for (int i = 0; i < data_len; i++) {
//         Serial.printf("0x%02X ", collected_data[i]);
//     }
//     Serial.println("");
  
//     /** Send the data package */
//     if (api.lorawan.send(data_len, (uint8_t *) & collected_data, 2, true, 1)) {
//         Serial.println("Sending is requested");
//     } else {
//         Serial.println("Sending failed");
//     }

// }

// void loop() {

//     static uint64_t last = 0;
//     static uint64_t elapsed;
  
//     Serial.printf("LoRa region = %d\r\n", api.lorawan.band.get());
    
//     if ((elapsed = millis() - last) > OTAA_PERIOD) {
//         uplink_routine();
//         last = millis();
//     }
//     Serial.printf("Try sleep %ums..", OTAA_PERIOD);



//     api.system.sleep.all(OTAA_PERIOD);
//     Serial.println("Wakeup..");

//     digitalWrite( PA9, HIGH ); delay(500);
//     digitalWrite( PA9, LOW ); delay(500);

// }


uint8_t  node_device_eui[8] = {0xAC, 0x1F, 0x09, 0xFF, 0xFE, 0x0E, 0x49, 0x55} ;// {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x88} 
uint8_t  node_app_eui[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} ;// {0x0E, 0x0D, 0x0D, 0x01, 0x0E, 0x01, 0x02, 0x0E}
uint8_t  node_app_key[16] = {0x8F, 0x29, 0xB7, 0xC3, 0xA4, 0x18, 0xBC, 0x2D, 0x7F, 0x16, 0xF8, 0xE2, 0x5E, 0x9C, 0x90, 0x00};//{0x8F, 0x29, 0xB7, 0xC3, 0xA4, 0x18, 0xBC, 0x2D, 0x7F, 0x16, 0xF8, 0xE2, 0x5E, 0x9C, 0x90, 0x00} // {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3E}
//8F29B7C3A418BC2D7F16F8E25E9C9000
void setup()
{
    Serial.begin(115200, RAK_AT_MODE);

    // api.lorawan.appeui.set(node_app_eui, 8);
    // api.lorawan.appkey.set(node_app_key, 16);
    // api.lorawan.deui.set(node_device_eui, 8);

    // api.lorawan.band.set(4);
    // api.lorawan.njm.set(1);
    // api.lorawan.join();

    if (!api.lorawan.band.set(RAK_REGION_EU868)) {                                       // If the OTAA freqquency band setting is a failure, 
        Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");                  // ... then we informe the user
        return;                                                                       // ... and stop the program.
    }    

    if (!api.lorawan.deui.set(node_device_eui, 8)) {                               // If the DevEUI setting is a failure, 
        Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");            // ... then we informe the user
        return;                                                                       // ... and stop the program.
    }    
    if (!api.lorawan.appeui.set(node_app_eui, 8)) {                               // If the AppEUI setting is a failure, 
        Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");       // ... then we informe the user
        return;                                                                       // ... and stop the program.
    }
    if (!api.lorawan.appkey.set(node_app_key, 16)) {                               // If the AppKEY setting is a failure, 
        Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");       // ... then we informe the user
        return;                                                                       // ... and stop the program.
    }

    if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {                          // If we can't set LoRaWan Class to type A, 
        Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");          // ... then we informe the user
        return;                                                                       // ... and stop the program.
    }
    if (!api.lorawan.njm.set(RAK_LORA_OTAA)) {                                      // If we can't set the 'Network Join Mode' to OTAA
        Serial.printf("LoRaWan OTAA - set network join mode is incorrect! \r\n");          // ... then we informe the user
        return;                                                                       // ... and stop the program.
    }

    if (!api.lorawan.join()) {                                                      // If we didn't join the LoRa Network, ...
        Serial.printf("LoRaWan OTAA - join fail! \r\n");                                // ... We informe the user
        return;                                                                         // ... and stop the program.
    }
    //wait for Join success
    while (api.lorawan.njs.get() == 0){
      delay(10000);
      Serial.print("Waiting for Lorawan join...");
      api.lorawan.join();
    }

    if (!api.lorawan.adr.set(true)) {
      Serial.printf("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
      return;
    }
    if (!api.lorawan.rety.set(1)) {
        Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
        return;
    }
    if (!api.lorawan.cfm.set(1)) {
        Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
        return;
    }

}

void loop() {

    uint8_t payload[] = "example";

    if (api.lorawan.send(sizeof(payload), payload, 129, true, 1)) {
        Serial.println("Send Success");
        Serial.printf("Send confirm %s\r\n", api.lorawan.cfs.get() ? "Success" : "Fail");

    } else {
        Serial.println("Send fail");

    }

    delay(20000);
}
 
