/* ======================================================================
Function: decode_received_data
Purpose : send to serial received data in human format
Input   : size of data
          command of frame received
          pointer to the data
Output  : command code validated by payload size type reveived
Comments: if we had a command and payload does not match
          code as been set to 0 to avoid check in next
====================================================================== */
uint8_t decode_received_data(uint8_t len, uint8_t c, void * ppayload)
{
  // Show packet type name
  Debug("#   ");
  Debug(decode_frame_type(c));

  // Alive packet ?
  if ( c==RF_PL_ALIVE && len==sizeof(RFAlivePayload))
  {
    RFAlivePayload * p = (RFAlivePayload *) ppayload;
    Debug(decode_bat(p->vbat));
  }

  // ping/ping back packet ?
  else if ( (c==RF_PL_PING || c==RF_PL_PINGBACK) && len==sizeof(RFPingPayload))
  {
    RFPingPayload * p = (RFPingPayload *) ppayload;
    Debug(decode_bat(p->vbat));

    // RSSI from other side is sent only in pingback response
    if (c==RF_PL_PINGBACK)
      Debug(decode_rssi(p->rssi));
  }

  // Classic payload Packet for majority of sensors ?
  else if ( len==sizeof(RFPayload))
  {
    RFPayload * p = (RFPayload *) ppayload;

    decode_bat(p->vbat);

    if ( c==RF_PL_TEMP || c==RF_PL_TEMP_HUM || c==RF_PL_TEMP_LUX || c==RF_PL_TEMP_CO2)
    {
      decode_temp(p->sensor1);

      if (c==RF_PL_TEMP_HUM) decode_hum(p->sensor2);
      if (c==RF_PL_TEMP_LUX) decode_lux(p->sensor2);
      if (c==RF_PL_TEMP_CO2) decode_co2(p->sensor2);
      if (c==RF_PL_TH02)     decode_hum(p->sensor2);
    }
  }

  // not known, raw display packet
  else
  {
    uint8_t * p = (uint8_t *) ppayload;
    while (--len)
    {
      Debug(*p++,HEX);
      Debug(" ");
    }

    // here we did not validated known packet, so clear command
    // code for the rest of the operation
    c=0;
  }

  return (c);
}
/* ======================================================================
Function: decode_received_data
Purpose : send to serial received data in human format
Input   : node id
          rssi of data received
          size of data
          command of frame received
          pointer to the data
Output  : command code validated by payload size type reveived
Comments: if we had a command and payload does not match
          code as been set to 0 to avoid check in next
====================================================================== */
uint8_t decode_received_data(uint8_t nodeid, int8_t rssi, uint8_t len, uint8_t c, uint8_t * ppayload)
{
  char *    pjson = json_str;
  uint8_t * pdat = ppayload;
  char *    ptype ;

  // Show packet type name
  ptype = decode_frame_type(c);

  // Start our buffer string
  //sprintf_P(json_str, PSTR("{\"id\":%d, \"type\":\"%s\", \"rssi\":%d"), nodeid, ptype, rssi);
  sprintf_P(json_str, PSTR("{\"id\":%d, \"rssi\":%d"), nodeid, rssi);

  // this is for known packet command
  // Alive packet ?
  if ( c==RF_PL_ALIVE && len==sizeof(RFAlivePayload)) {
    sprintf_P(pbuf, PSTR("\"state\":%04X"), ((RFAlivePayload*)pdat)->status);
    add_json_data(json_str, pbuf);
    add_json_data(json_str, decode_bat(((RFAlivePayload*)pdat)->vbat,""));
  } else if ( (c==RF_PL_PING || c==RF_PL_PINGBACK) && len==sizeof(RFPingPayload)) {
    // ping/ping back packet ?
    sprintf_P(pbuf, PSTR("\"state\":%04X"), ((RFAlivePayload*)pdat)->status);
    add_json_data(json_str, pbuf);
    // Vbat is sent only on emiting ping packet, not ping back
    if (c==RF_PL_PING )
      add_json_data(json_str, decode_bat(((RFPingPayload*)pdat)->vbat,""));

    // RSSI from other side is sent only in pingback response
    // this is the 2nd rssi value, we call it myrssi
    if (c==RF_PL_PINGBACK){
      sprintf_P(pbuf, PSTR("\"myrssi\":%d"), rssi);
      add_json_data(json_str, pbuf);
    }
  }
  // payload Packet with datas
  // we need at least size of payload > 2
  // 1 payload command + 1 sensor type + 1 sensor data)
  // and is one of our known data code. This is for received data
  else if ( isPayloadData(c) && len>2) {
    uint8_t data_size ;
    uint8_t data_type ;
    uint8_t l ;
    char *  pval;
    boolean error ;

    // Ok we set up on 1st data field
    data_type = *(++pdat);
    l = len -1;

    // Loop through all data contained into the payload
    // discard 1st byte on each, which is header data code
    do {
      // each sensor type can have 4 values sent,
      char str_idx[] = " ";
      data_size = 0;
      pval= NULL;
      error = false;

      // If index of sensor value is > 0 change string
      // label adding the index if at least 2 values
      // i.e if 2 sensor temp are sent/received the
      // result will look in JSON like
      // ie : {temp:20.1, temp1:22.11, ...}
      *str_idx = '0' + (data_type & ~RF_DAT_SENSOR_MASK);

      // the first we don't add index number this save 1 char
      if (*str_idx=='0')
        *str_idx='\0';

      if (isDataTemp(data_type) && l>=sizeof(s_temp)) {
        // Temperature, and have enought data ?
        pval = decode_temp(((s_temp*)pdat)->temp, str_idx);
        data_size = sizeof(s_temp);
      } else if (isDataHum(data_type) && l>=sizeof(s_hum)) {
        // Humidity, and have enought data ?
        pval = decode_hum(((s_hum*)pdat)->hum, str_idx);
        data_size = sizeof(s_hum);
      } else if (isDataLux(data_type) && l>=sizeof(s_lux)) {
        // Luminosity and have enought data ?
        pval =  decode_lux(((s_lux*)pdat)->lux, str_idx);
        data_size = sizeof(s_lux);
      } else if (isDataCO2(data_type) && l>=sizeof(s_co2)) {
        // CO2 and have enought data ?
        pval = decode_co2(((s_co2*)pdat)->co2, str_idx);
        data_size = sizeof(s_co2);
      } else if (isDataVolt(data_type) && l>=sizeof(s_volt)) {
        // voltage and have enought data ?
        pval = decode_volt(((s_volt*)pdat)->volt, str_idx);
        data_size = sizeof(s_volt);
      }  else if (isDataBat(data_type) && l>=sizeof(s_volt)) {
        // battery (same payload as volt) and have enought data ?
        pval = decode_bat(((s_volt*)pdat)->volt, str_idx);
        data_size = sizeof(s_volt);
      } else if (isDataRSSI(data_type) && l>=sizeof(s_rssi)) {
        // RSSI and have enought data ?
        pval =  decode_rssi(((s_rssi*)pdat)->rssi, str_idx);
        data_size = sizeof(s_rssi);
      } else if (isDataCounter(data_type) && l>=sizeof(s_counter)) {
        // counter and have enought data ?
        pval =  decode_counter(((s_counter*)pdat)->counter, str_idx);
        data_size = sizeof(s_counter);
      } else if (isDataLowBat(data_type) && l>=sizeof(s_lowbat)) {
        // lowbat and have enought data ?
        pval =  decode_lowbat(((s_lowbat*)pdat)->lowbat, str_idx);
        data_size = sizeof(s_lowbat);
      } else if (isDataDigitalIO(data_type) && l>=sizeof(s_io_digital)) {
        // digital I/0
        pval =  decode_digital_io(((s_io_digital*)pdat)->digital,
                                  ((s_io_digital*)pdat)->code - RF_DAT_IO_DIGITAL);
        data_size = sizeof(s_io_digital);
      } else if (isDataAnalogIO(data_type) && l>=sizeof(s_io_analog)) {
        // analog I/O
        pval =  decode_analog_io(((s_io_analog*)pdat)->analog,
                                 ((s_io_analog*)pdat)->code - RF_DAT_IO_ANALOG);
        data_size = sizeof(s_io_analog);
      } else {
        // Unknown data code, so we can't check data value
        // nor size, so we decide to discard the
        // end of this frame
        ULPNP_DebugF("Parsing error");
        error = true;
      }

/*
      ULPNP_DebugF("[0x");
      ULPNP_Debug(data_type,HEX);
      ULPNP_DebugF("] -> l=");
      ULPNP_Debug(l);
      ULPNP_DebugF(" added=");
      ULPNP_Debug(data_size);
      ULPNP_DebugF(" pval='");
      ULPNP_Debug(pval);
      ULPNP_DebugF("' next=");
      */

      // Something to add ?
      if (!error && data_size && pval) {
        // Add to JSon string
        add_json_data(json_str, pval);

        // remove data size we just worked on
        l-= data_size;

        // Rest some data after the code
        if (l>=2) {
          pdat+=data_size; // Pointer to next data on buffer
          data_type=*pdat;         // get next data field

          //ULPNP_Debug(data_type,HEX);
        } else {
          //ULPNP_DebugF("none");
        }
      }

      //ULPNP_Debugln();

    } // while data
    while(l>1 && !error);

  } else {
    // not known data code, raw display packet
    uint8_t * p = (uint8_t *) ppayload;

    // send raw values
    strcat(json_str, ", \"raw\":\"");

    // Add each received value
    while (len--)
      sprintf_P(&json_str[strlen(json_str)], PSTR("%02X "), *p++);

    strcat(json_str, "\"");

    // here we did not validated known packet, so clear command
    // code for the rest of the operation
    c=0;
  }

  // End our buffer string
  strcat(json_str, "}");
  ULPNP_Debug(json_str);

  return (c);
}