////////////////////////////////////////////////////////////////////////////////////////////////////
//ANDRUINO LIBRARY
//A.Scavuzzo
//www.andruino.it
//ETH JSON
////////////////////////////////////////////////////////////////////////////////////////////////////


void json_NRF24L();
void json_Arduino_io(byte mode);
void json_Arduino_json_NRF24Lio(byte index);
void json_Arduino_json_IO();
void json_Arduino_json_Analog();
void json_Arduino_json_Vars();
void json_Arduino_Timers();
void json_Arduino_json_System();
void json_comma();
short json_SearchDigitalPin (uint8_t max_index_vect, DigitalPin * PinArray, uint8_t port, uint8_t mode );
void json_Arduino_DigitalSingle(DigitalPin *PinArray, byte index);
void json_Arduino_AnalogSingle(AnalogPin *PinArray, byte index);
void json_Arduino_VariableSingle(Variable *PinArray, byte index);

void RemoteDigitalSetup(byte indexV, byte mode, byte state, bool inv);
void RemoteDigitalSetupNRF24L(uint8_t indexV, byte mode, uint8_t value, bool inv, byte indexModule);

void eep_Write_HttpRequest_time();


/*
  JSON format
  {
  "arduino_io":{"INFO":["3"],"DIGITALS":[["3","pwm","0","0"],["4","out","1","0"],["5","out","0","0"],["6","out","0","0"],["7","out","0","0"],["8","out","0","0"],["9","in","0","0"],["10","out","1","0"],["11","out","0","0"],
  ["12","out","0","0"],["13","out","0","0"],["14","out","0","0"],["15","out","0","0"],["16","out","0","0"],["17","out","0","0"],["18","out","0","0"],["19","out","0","0"],["20","out","0","0"],["21","out","0","0"],["22","in","0","0"],["23","in","0","0"],["24","in","0","0"],["25","in","0","0"],["26","out","0","0"],["27","out","0","0"],["28","out","0","0"],
  ["29","out","0","0"]], "ANALOGS":[2.464,2.416,2.075,1.835,1.739,1.743,1.666,1.532,1.412,1.354,1.321,1.253,1.287,1.239,1.297,1.153]},
  "arduino_var":{"VARIABLES":[52.900,23.600,3.000,3423.000,0.000,0.183,0.289,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000]},

  "NRF24L_io_0":{"INFO":["55381","02","3281","88","344","0","1001","2","0"],"DIGITALS":[],"ANALOGS":[]},
  "NRF24L_var_0":{"VARIABLES":[0.000,0.000,0.000,0.000,55380.000]},

  "ardu_tim":[255,255,255,255,255,255,255,255,255,255,255,255],
  "ardu_sys":{"ardu_date":[0,9,15,33],"ardu_fd2":["XXXX","1111","255.255.255.255","21414"],"ardu_fd":[3,0,0,1,0,0,7.000,7.000]}
  }
*/


void (* Riavvia)(void) = 0;





//search pin in the array
//return the index of the array
//-1 if it is not found
short json_SearchDigitalPin (uint8_t max_index_vect, DigitalPin * PinArray, uint8_t port, uint8_t mode ) {

  short j;

  //if mode = ALL (3), the PinArray[j].mode is bypassed, so all the pin will be displayed
  for (j = 0; j < max_index_vect; j++)  {
    if ((PinArray[j].mode == mode || mode == ALL) &&  PinArray[j].used == true  && PinArray[j].pin == port) {   //if it is output and is used
      //Serial.print("index_array:"); Serial.println(j);
      return (j);
    }
  }
  return (-1);
}


void RemoteDigitalWrite(byte indexV, int duration, char *action)                                                //modify the digital pin state (output high or low, or put the buffer in input mode)
{


  //json_SearchDigitalPin (uint8_t max_index_vect, DigitalPin *PinArray, uint8_t port, uint8_t mode )
  short index_array = json_SearchDigitalPin(sizeof(base_digital_pins_used), ArduinoIO, indexV, OUTPUT);
  if (index_array < 0) {
    //   IF_SERIAL_DEBUG_ARRAY(printf_P(PSTR("Pin not found on the list\r\n")));
    return;
  }

  //Serial.print("index_array:"); Serial.println(index_array);


  // Switch port as requested
  if (strcmp(action, "1") == 0) {
    writeDig(ArduinoIO[index_array], true);                               //configures the pin as output and put the pin high
    ArduinoIO[index_array].time_counter = duration;
  } else if  (strcmp(action, "0") == 0) {
    writeDig(ArduinoIO[index_array], false);                              //configures the pin as output and put the pin low
  } else if  (strcmp(action, "0P") == 0 || strcmp(action, "1P") == 0) {             //a pulse request is arrived

    if (duration == 0)
      pulse(ArduinoIO[index_array], PIN_PULSE_WIDTH);                            //A Pulse is given (default 500ms)
    else
      pulse(ArduinoIO[index_array], duration);                                   //A Pulse is given
  }
}

//used to setup the PIN by software (change from input to output, change the INV)
void RemoteDigitalSetup(byte indexV, byte mode, byte state, bool inv)
{
  //json_SearchDigitalPin (uint8_t max_index_vect, DigitalPin *PinArray, uint8_t port, uint8_t mode )
  short index_array = json_SearchDigitalPin(sizeof(base_digital_pins_used), ArduinoIO, indexV, ALL);
  if (index_array < 0) {
    //   IF_SERIAL_DEBUG_ARRAY(printf_P(PSTR("Pin not found on the list\r\n")));
    return;
  }
  if (mode == PWM)
    setupPWM(ArduinoIO[index_array], mode, state);	                      //setup + write the pwm value from flash content
  else
    setupDig(ArduinoIO[index_array], mode, state, inv);
}



//////////////////
//Read Arduino
//0 -- read all datas
//1 -- read Arduino All IO and systems (analogs + digitals)
//2 -- read Arduino IO and systems (digitals)
//3 -- read Arduino IO and systems (analogs)
//4 -- read XBee IO and systems
//5 -- read Variables IO and systems
//
void json_Arduino_SendAll(byte mode)
{

  //if json trasmit is false, exit
  if (command_from_server_glo == true)
    return;


  ethbuff_ClientPrint(F("{"));            //open first bracket

  switch (mode) {

    case 1:
      json_Arduino_io(0);           //read All Arduino IO (digital + analog)
      ethbuff_ClientPrint(F(","));
      json_Arduino_json_System();          //read Arduino system vars
      break;
    case 2:
      json_Arduino_io(1);           //read Arduino IO (digital)
      ethbuff_ClientPrint(F(","));
      json_Arduino_json_System();          //read Arduino system vars
      break;
    case 3:
      json_Arduino_io(2);           //read Arduino IO (analog)
      ethbuff_ClientPrint(F(","));
      json_Arduino_json_System();          //read Arduino system vars
      break;
    case 4:
      json_Arduino_json_System();          //read Arduino system vars
      break;

    case 5:
      json_Arduino_json_Vars();          //read Arduino Variables
      ethbuff_ClientPrint(F(","));
      json_Arduino_json_System();          //read Arduino system vars
      break;

    case 6:
      json_Arduino_json_System();          //read Arduino system vars
      break;


    default:
      json_Arduino_io(0);           //read Arduino IO
      ethbuff_ClientPrint(F(","));
      json_Arduino_json_Vars();          //read Arduino Variables
      ethbuff_ClientPrint(F(","));
#if NRF24L_ENABLE == 1
      for (byte k = 0; k < NRF24LMaxModules; k++) {
        if (SystemNRF24LPins[k].RNF24LAddr != 0) {
          json_Arduino_json_NRF24Lio(k);         //read NRF24L IO, full json
          ethbuff_ClientPrint(F(","));
        }
      }
#endif

      json_Arduino_json_System();          //read Arduino system vars
      //break;
  }

  //FIX 8.0
  ethbuff_ClientPrint(F("}\r\n"));               //close last bracket
  delay(1);


}

void json_comma() {
  ethbuff_ClientPrint(F(","));                     //
}


void json_Arduino_io(byte mode)
{
  ethbuff_ClientPrint(F("\"arduino_io\":{\"INFO\":["));                  //open JSON bracket, INFO ARDUINO
  json_PrintDataComma(network_access, false, true);
  json_PrintDataComma(network_client_access, false, false);
  ethbuff_ClientPrint(F("],"));
  switch (mode) {
    case 1:
      json_Arduino_json_IO();
      break;
    case 2:
      json_Arduino_json_Analog();
      break;
    case 4:
      json_Arduino_json_System();                //read Arduino system vars
      break;
    default:
      json_Arduino_json_IO();
      ethbuff_ClientPrint(F(","));
      json_Arduino_json_Analog();
  }
  ethbuff_ClientPrint(F("}"));                             //close JSON bracket
}


#if NRF24L_ENABLE == 1
void json_NRF24L()
{
  bool second_data = false;

  ethbuff_ClientPrint(F("\"arduino_nrf24l\":{"));                  //open JSON bracket, INFO ARDUINO

  for (byte k = 0; k < NRF24LMaxModules; k++) {
    if (SystemNRF24LPins[k].RNF24LAddr != 0) {
      if (second_data == true)
        ethbuff_ClientPrint(F(","));
      else
        second_data = true;

      json_Arduino_json_NRF24Lio(k);          //read NRF24L IO, short json (true)
    }
  }

  ethbuff_ClientPrint(F("}"));                             //close JSON bracket
}
#endif




void json_Arduino_json_IO()
{
  byte ReadChannel;
  //    float analogValue;
  int sensorReading;
  boolean second_data = false;
  //Arduino IO JSON STREAM
  ethbuff_ClientPrint(F("\"DIGITALS\":["));                  //open JSON bracket
  second_data = false;
  for (int i = 0; i < sizeof(base_digital_pins_used); i++) {    //MAXPIN
    //   if (ArduinoIO[i].used == 1) {
    if (second_data == true)
      ethbuff_ClientPrint(F(","));
    else
      second_data = true;
    //INPUT DIGITAL
    if (ArduinoIO[i].mode == 0) {                   //0=in
      ReadChannel = read(ArduinoIO[i]).state;                       //read input/output pins
      json_FormatDigital(ArduinoIO[i].pin, "in", ReadChannel, ArduinoIO[i].pulse, 0);
      //OUTPUT DIGITAL
    } else if (ArduinoIO[i].mode == 1) {            //1=out
      ReadChannel = read(ArduinoIO[i]).state;                       //read input/output pins
      json_FormatDigital(ArduinoIO[i].pin, "out", ReadChannel, ArduinoIO[i].pulse, ArduinoIO[i].inv);
      ArduinoIO[i].pulse = false;
      //PWM DIGITAL
    } else if (ArduinoIO[i].mode == 2) {
      ReadChannel = ArduinoIO[i].state;                       //read pwm var
      json_FormatDigital(ArduinoIO[i].pin, "pwm", ReadChannel, 0, 0);
    }
    //   }
  }
  ethbuff_ClientPrint("]");                     //close JSON bracket

}


void json_Arduino_DigitalSingle(DigitalPin *PinArray, byte index)
{

  ethbuff_ClientPrint(F("{single:{\"DIGITAL\":["));
  json_PrintDataComma(PinArray[index].pin, true, true);
  json_PrintDataComma(PinArray[index].mode, true, true);
  json_PrintDataComma(PinArray[index].state, true, true);
  json_PrintDataComma(PinArray[index].inv, true, true);
  json_PrintDataComma(PinArray[index].alarm, true, true);
  json_PrintDataComma(PinArray[index].time_counter, true, true);
  json_PrintDataComma(PinArray[index].enable_limits, true, true);
  json_PrintDataComma(PinArray[index].Limit.cnt, true, true);
  json_PrintDataComma(PinArray[index].Limit.events_cnt, true, true);
  json_PrintDataComma(PinArray[index].Limit.max_events, true, false);
  ethbuff_ClientPrint(F("]}}"));
}


void json_Arduino_AnalogSingle(AnalogPin *PinArray, byte index)
{

  ethbuff_ClientPrint(F("{single:{\"ANALOG\":["));
  json_PrintDataComma(PinArray[index].pin, true, true);
  json_PrintDataCommaFloat(PinArray[index].value, 5, true, true);
  json_PrintDataComma(PinArray[index].state, true, true);
  json_PrintDataComma(PinArray[index].used, true, true);
  json_PrintDataComma(PinArray[index].max, true, true);
  json_PrintDataComma(PinArray[index].min, true, true);
  json_PrintDataComma(PinArray[index].enable_limits, true, true);
  json_PrintDataComma(PinArray[index].Limit.high_cnt, true, true);
  json_PrintDataComma(PinArray[index].Limit.low_cnt, true, true);
  json_PrintDataComma(PinArray[index].Limit.events_cnt, true, true);
  json_PrintDataComma(PinArray[index].Limit.max_events, true, false);
  ethbuff_ClientPrint(F("]}}"));
}

void json_Arduino_VariableSingle(Variable *PinArray, byte index)
{

  ethbuff_ClientPrint(F("{single:{\"VARIABLE\":["));
  json_PrintDataComma(PinArray[index].pin, true, true);
  json_PrintDataCommaFloat(PinArray[index].value, 6, true, true);


  json_PrintDataComma(PinArray[index].max, true, true);
  json_PrintDataComma(PinArray[index].min, true, true);
  json_PrintDataComma(PinArray[index].enable_limits, true, true);
  json_PrintDataComma(PinArray[index].Limit.high_cnt, true, true);
  json_PrintDataComma(PinArray[index].Limit.low_cnt, true, true);
  json_PrintDataComma(PinArray[index].Limit.events_cnt, true, true);
  json_PrintDataComma(PinArray[index].Limit.max_events, true, false);
  ethbuff_ClientPrint(F("]}}"));
}



void json_error(byte error_type)
{
  ethbuff_ClientPrint(F("{\"error\":["));
  ethbuff_ClientPrint(error_type);
  ethbuff_ClientPrint(F("]}"));
}



void json_Arduino_json_Analog()
{
  byte ReadChannel;
  //    float analogValue;
  int sensorReading;
  boolean second_data = false;
  ethbuff_ClientPrint(F("\"ANALOGS\":["));
  second_data = false;
  for (int i = 0; i < sizeof(base_analog_pins_used); i++)
  {
    if (second_data == true)
      ethbuff_ClientPrint(F(","));
    else
      second_data = true;
    //sensorReading = readAnalog(ArduinoAnalog[i]).value;
    //analogValue = sensorReading * ADC_STEP;
    ArduinoAnalog[i].value = analogRead(ArduinoAnalog[i].pin) * ADC_STEP;

    //unsigned long int pippo =  (int)&ADC_STEP;
    //Serial.print(F("Float value")); Serial.print(ArduinoAnalog[i].value, 2);Serial.print(F(", pin"));Serial.print(F("Index")); Serial.print(i);Serial.print(F(", pin")); Serial.print(ArduinoAnalog[i].pin);Serial.print(F(", ADC_STEP")); Serial.print(ADC_STEP,3);Serial.print(F(", ADC_STEP addr")); Serial.println(pippo);

    json_FormatAnaVar(ArduinoAnalog[i].pin, "ana", ArduinoAnalog[i].value);   //full or short mode json

  }
  ethbuff_ClientPrint(F("]"));                     //close JSON bracket
}




void json_Arduino_json_Vars()
{
  byte ReadChannel;
  float analogValue;
  int sensorReading;
  boolean second_data = false;
  //ARDUINO VARIABLES


  ethbuff_ClientPrint(F("\"arduino_var\":{\"VARIABLES\":["));  //open JSON bracket

  second_data = false;
  for (int i = 0; i < sizeof(base_variable_used); i++)
  {
    if (second_data == true) {
      ethbuff_ClientPrint(F(","));
    }
    else
      second_data = true;

    json_FormatAnaVar(base_variable_used[i], "var", Arduino_User_var[i].value);                      //short mode json  or short mode json

  }

  ethbuff_ClientPrint(F("]}"));                //close JSON bracket


}


void json_Arduino_json_System()
{


  ////////////////////////////////
  //ARDUINO TIMERS
  boolean second_data = false;
  ethbuff_ClientPrint(F("\"ardu_tim\":["));  //open JSON bracket
  for (int i = 0; i < MAX_TIMERS; i++)
  {
    if (second_data == true) {
      ethbuff_ClientPrint(F(","));
    }
    else
      second_data = true;

    uint8_t port_number;                //255 means timer not used
    port_number = eeprom_read_byteNEW (FLA_TIMERS_ADDRESS + BYTES_FOR_EACH_TIMER * i);
    ethbuff_ClientPrint(port_number);
  }
  // ethbuff_ClientPrint("],");               //close JSON bracket

  ////////////////////////////////
  //Date and feeds
  ////////////////////////////////
  //ardu_date

  byte not_used = 0;

  ethbuff_ClientPrint(F("],\"ardu_sys\":{\"ardu_date\":["));
  json_PrintDataComma(days_counter, false, 1);
  json_PrintDataComma(hours_counter, false, 1);
  json_PrintDataComma(minutes_counter, false, 1);
  json_PrintDataComma(seconds_counter, false, 0);

  if (system_json_data_scan == 1) {
    system_json_data_scan++;
    ethbuff_ClientPrint(F("],\"ardu_cfg\":["));
    //sketch config
    json_PrintDataCommaFloat(SKETCH_VERSION, 3, false, 1);                     //sketch version
    json_PrintDataComma((unsigned int)ETHERNET_SHIELD, true, 1);
    json_PrintDataComma((unsigned int)ETHERNET_SHIELD_V2, true, 1);
    json_PrintDataComma((unsigned int)WIFI_ESP8266_SHIELD, true, 1);
    json_PrintDataComma((unsigned int)NRF24L_ENABLE, true, 1);
    json_PrintDataComma((unsigned int)Dallas_DS18B20, true, 1);                              //Dallas_DS18B20
    json_PrintDataComma((unsigned int)THERMO_ADAFRUIT_MAX31855, true, 1);                    //THERMO_ADAFRUIT_MAX31855
    json_PrintDataComma((unsigned int)POWER_CONSUMPTION_ENABLE, true, 1);                    //POWER_CONSUMPTION_ENABLE
    json_PrintDataComma((unsigned int)THERMO_ADAFRUIT_DHT, true, 1);                         //THERMO_ADAFRUIT_DHT
    json_PrintDataComma((unsigned int)THERMO_ADAFRUIT_DHT2, true, 1);                        //THERMO_ADAFRUIT_DHT2
    json_PrintDataComma(not_used, true, 1);                                                  //ex DATA_LOGGING_DB  (not_used)
    json_PrintDataComma(not_used, true, 1);                                                   //ex CHECK_LIMITS
    json_PrintDataComma((unsigned int)SERVER_MODE, true, 1);                                 //SERVER_MODE
    json_PrintDataComma(not_used, true, 1);                                                   //ex CLIENT_MODE
    json_PrintDataComma((unsigned int)ETHERNET_DHCP, true, 1);                               //14
    json_PrintDataComma((unsigned int)MCU_ESP8266, true, 1);                                 //15
    json_PrintDataComma((unsigned int)MCU_STM32, true, 1);                                    //11
    json_PrintDataComma(not_used, true, 0);                                    //11
  }
  else if (system_json_data_scan == 2) {
    system_json_data_scan++;
#if (WIFI_ESP8266_SHIELD == 1 || MCU_ESP8266 == 1)
    ethbuff_ClientPrint(F("],\"ardu_network\":["));
    json_PrintDataComma(WiFi.SSID(), true, 1);                            //0
    json_PrintDataComma(Get_Wifi_strength(), true, 1);                    //1
    json_PrintDataComma(wifi_signal_bars, false, 1);                      //2
    json_PrintDataComma(not_used, false, 1);                              //3
    json_PrintDataComma(not_used, false, 1);                              //4
    json_PrintDataComma(not_used, false, 1);                              //5
    json_PrintDataComma(not_used, false, 1);                              //6
    json_PrintDataComma(not_used, false, 1);                              //7
    json_PrintDataComma(not_used, true, 0);
#endif
  } else
    system_json_data_scan = 0;

  //ardu_fd
  ethbuff_ClientPrint(F("],\"ardu_fd\":["));
  json_PrintDataComma(network_access, false, 1);
  json_PrintDataComma(not_used, false, 1);                                    //Wifi bars (1 to 5)
  json_PrintDataComma(client_fail_connected_cnt, false, 1);                   //10.4 (WAS DDNS)
  json_PrintDataComma(push_success_cnt, false, 1);
  json_PrintDataComma(push_fail_cnt, false, 1);
  json_PrintDataComma(client_cumulated_fails_cnt, false, 1);
  json_PrintDataCommaFloat(SKETCH_VERSION, 3, false, 1);                        //sketch version
  json_PrintDataComma(http_server_performance_ms, false, 1);       //http server performance
  json_PrintDataComma(http_client_performance_ms, false, 1);       //http client performance
  json_PrintDataComma(server_fail_cnt, false, 1);                 //http server_fail_cnt
  json_PrintDataComma(eth_restart_cnt, false, 1);                 //http server_fail_cnt
  json_PrintDataComma(client_consecutive_fails_cnt, false, 1);        //http client_consecutive_fails_cnt
  json_PrintDataComma(network_client_access, false, 1);           //success client connections
  json_PrintDataComma(fault_restart, false, 1);                   //fault_restart
  json_PrintDataComma(freeRam(), false, 1);        //
  json_PrintDataComma(http_client_performance_max_ms, false, 0);        //

  //ardu_fd2
  ethbuff_ClientPrint(F("],\"ardu_fd2\":["));
  json_PrintDataComma(push_user, true, 1);                                   //0
  json_PrintDataComma(pin_push_flash, true, 1);                              //1
  json_PrintDataComma(board_name_array, true, 1);                            //2
  json_PrintDataComma(pairing_id, true, 1);                                  //3
  json_PrintDataComma(andruino_it_ip_address, true, 1);                      //4
  json_PrintDataComma(arduino_ip_address, true, 1);                          //5
  json_PrintDataComma(server_port_number, true, 1);                          //6
  json_PrintDataComma(client_sendjson_active_req_every_sec, true, 1);        //7
#if SLEEP_MODE == 1  
  json_PrintDataComma((SLEEP_WAKEUP_MIN*60), true, 1);                       //8
#else
  json_PrintDataComma(ping_req_every_sec, true, 1);                          //8
#endif
  json_PrintDataComma(not_used, true, 1);                                    //9 NU9
#if SLEEP_MODE == 1  
  json_PrintDataComma((SLEEP_WAKEUP_MIN*60), true, 1);                        //10
#else
  json_PrintDataComma(client_sendjson_notactive_req_every_sec, true, 1);     //10
#endif
  json_PrintDataComma(ethernet_id, true, 1);                                 //11
  json_PrintDataComma(ap_enabled, true, 0);                                  //12

  ethbuff_ClientPrint(F("]}"));


}


//type = 1  {["3","pwm","0"]}  port/mode/value
//type = 0  {"port":"dig3","mode":"pwm","val":"0"}
void  json_FormatDigital (byte port, char *mode, byte value, boolean pulse, boolean inv) {
  char buffer[60];
  sprintf(buffer, "[\"%d\",\"%s\",\"%d\",\"%d\",\"%d\"]", port, mode, value, pulse, inv);                         //short mode json
  ethbuff_ClientPrint(buffer);
}







//{"port":"var0","mode":"var","val":"?"}
/*void  json_FormatAna (byte port,char *mode, unsigned int value) {
  char buffer[50];
  //mode=var, ana
  sprintf(buffer,"{\"port\":\"%s%d\",\"mode\":\"%s\",\"val\":\"%d\"}",mode, port,mode,value);
  ethbuff_ClientPrint(buffer);
  delay(DELAY_TX_ETHERNET);
  }*/



void  json_FormatAnaVar (byte port, char *mode, float value) {

  ethbuff_ClientPrint(value, 3);                                                               //short mode json

}


void  json_PrintDataComma (char *datas, bool quota, bool comma) {

  if (quota)
    ethbuff_ClientPrint(F("\""));
  ethbuff_ClientPrint(datas);
  if (quota)
    ethbuff_ClientPrint(F("\""));
  if (comma)
    ethbuff_ClientPrint(F(","));
}
/*
  void  json_PrintDataComma (int datas, bool quota, bool comma) {
  if(quota)
    ethbuff_ClientPrint(F("\""));
  ethbuff_ClientPrint(datas);
  if(quota)
    ethbuff_ClientPrint(F("\""));
  if (comma)
    ethbuff_ClientPrint(F(","));
  }
*/
void  json_PrintDataComma (unsigned int datas, bool quota, bool comma) {
  if (quota)
    ethbuff_ClientPrint(F("\""));
  ethbuff_ClientPrint(datas);
  if (quota)
    ethbuff_ClientPrint(F("\""));
  if (comma)
    ethbuff_ClientPrint(F(","));
}
/*
  void  json_PrintDataComma (long int datas, bool quota, bool comma) {
  if(quota)
    ethbuff_ClientPrint(F("\""));
  ethbuff_ClientPrint(datas);
  if(quota)
    ethbuff_ClientPrint(F("\""));
  if (comma)
    ethbuff_ClientPrint(F(","));
  }
*/

void  json_PrintDataComma (unsigned int datas, int base, bool quota, bool comma) {
  if (quota)
    ethbuff_ClientPrint(F("\""));
  ethbuff_ClientPrint(datas, base);
  if (quota)
    ethbuff_ClientPrint(F("\""));
  if (comma)
    ethbuff_ClientPrint(F(","));
}
void  json_PrintDataCommaFloat (float datas, byte digits, bool quota, bool comma) {
  if (quota)
    ethbuff_ClientPrint(F("\""));
  ethbuff_ClientPrint(datas, digits);
  if (quota)
    ethbuff_ClientPrint(F("\""));
  if (comma)
    ethbuff_ClientPrint(F(","));
}


void  json_PrintDataComma (String datas, bool quota, bool comma) {
  char buf_char[20];
  datas.toCharArray(buf_char, 20);
  if (quota)
    ethbuff_ClientPrint(F("\""));
  ethbuff_ClientPrint(buf_char);
  if (quota)
    ethbuff_ClientPrint(F("\""));
  if (comma)
    ethbuff_ClientPrint(F(","));
}






#if NRF24L_ENABLE == 1
void json_Arduino_json_NRF24Lio(byte index)
{
  // Send requested information
  byte ReadChannel;
  //    float analogValue;
  float sensorReading;
  boolean second_data = false;


  //NRF24L IO
  ethbuff_ClientPrint(F("\"NRF24L_io_"));                                                //open JSON bracket
  ethbuff_ClientPrint(index);
  //"NRF24L_io_0":{"INFO":["30","02","3290","88","344","1","1002","2","0"]
  ethbuff_ClientPrint(F("\":{\"INFO\":["));                                            //INFO NRF
  json_PrintDataComma(SystemNRF24LPins[index].samples, true, 1);
  json_PrintDataComma(SystemNRF24LPins[index].RNF24LAddr, OCT, true, 1);
  json_PrintDataComma(SystemNRF24LPins[index].Supply, 2, true, 1);
  json_PrintDataComma(SystemNRF24LPins[index].sleep_time_value, true, 1);
  json_PrintDataComma(SystemNRF24LPins[index].alive_counter, true, 1);
  json_PrintDataComma(SystemNRF24LPins[index].alive_fail_counter, true, 1);
  json_PrintDataComma(SystemNRF24LPins[index].fw_version, true, 1);
  json_PrintDataComma(SystemNRF24LPins[index].pa_level, true, 1);
  json_PrintDataComma(SystemNRF24LPins[index].leaf, true, 0);

  ethbuff_ClientPrint(F("],\"DIGITALS\":["));                                          //DIGITALS
  second_data = false;
  for (int i = 0; i < NRF24LMaxDigitalPin; i++)
  {
    if (SystemNRF24LPins[index].DigPin[i].used && SystemNRF24LPins[index].DigPin[i].mode != 2) {        //find digital input/outputs
      if (second_data == true)
        ethbuff_ClientPrint(F(","));
      else
        second_data = true;

      if (SystemNRF24LPins[index].DigPin[i].mode == 0) {
        ReadChannel = (byte) SystemNRF24LPins[index].DigPin[i].state;         //read  DIGITAL pins (PREVIOUSLY READ from var)
        json_FormatDigital(SystemNRF24LPins[index].DigPin[i].pin, "in", ReadChannel, 0, 0);
      } else {
        ReadChannel = (byte) SystemNRF24LPins[index].DigPin[i].state;         //read digital outputs
        json_FormatDigital(SystemNRF24LPins[index].DigPin[i].pin, "out", ReadChannel, 0, SystemNRF24LPins[index].DigPin[i].inv);
        //////// IF_SERIAL_DEBUG_NRF(printf_P(PSTR("@@@@@@@@@@@@@@@@@NRF pin sent in JSON : %d, value:%d, indexModule:%d\r\n"), SystemNRF24LPins[index].DigPin[i].pin, ReadChannel, index));
      }
    }
  }
  ethbuff_ClientPrint(F("],\"ANALOGS\":["));
  second_data = false;
  for (int i = 0; i < NRF24LMaxAnalogPin; i++)
  {
    if (SystemNRF24LPins[index].AnaPin[i].used) {        //find analog
      if (second_data == true)
        ethbuff_ClientPrint(F(","));
      else
        second_data = true;

      sensorReading = ((float)SystemNRF24LPins[index].AnaPin[i].state) * SystemNRF24LPins[index].AdcStep;   //read  ANALOG  pins (PREVIOUSLY READ from var)
      json_FormatAnaVar(SystemNRF24LPins[index].AnaPin[i].pin, "ana", sensorReading);
    }
  }
  ethbuff_ClientPrint(F("]},\"NRF24L_var_"));                                                //open JSON bracket
  ethbuff_ClientPrint(index);
  ethbuff_ClientPrint(F("\":{\"VARIABLES\":["));
  second_data = false;
  //IF_SERIAL_DEBUG_NRF(printf_P(PSTR("VARIABLE NUM: %d\r\n"), SystemNRF24LPins[index].var_num));
  for (int i = 0; i < SystemNRF24LPins[index].var_num; i++)
  {
    if (second_data == true)
      ethbuff_ClientPrint(F(","));
    else
      second_data = true;
    json_FormatAnaVar(i, "var", SystemNRF24LPins[index].VarPin[i].value);
  }
  ethbuff_ClientPrint(F("]}"));                      //close JSON bracket
}


void RemoteDigitalWriteNRF24L(uint8_t indexV, uint8_t value, byte indexModule, uint16_t duration)                                               //modify the digital pin state (output high or low, or put the buffer in input mode)
{
  bool ok;

  //indexV  2,3,10
  //indexModule: 0,1,2,3

  IF_SERIAL_DEBUG_NRF(printf_P(PSTR("#####################################################################DIGITAL OUT PIN preparing data for the remote sensor\r\n")));
  IF_SERIAL_DEBUG_NRF(printf_P(PSTR("indexV: %d, value:%d, indexModule:%d\r\n"), indexV, value, indexModule));

  short j = json_SearchDigitalPin (NRF24LMaxDigitalPin, SystemNRF24LPins[indexModule].DigPin, indexV, OUTPUT);
  if (j < 0) {
    IF_SERIAL_DEBUG_NRF(printf_P(PSTR("NRF module not found on the list\r\n")));
    return;
  }

  IF_SERIAL_DEBUG_NRF(printf_P(PSTR("Remote pin found: IndexPin:%d, state%d\r\n"), j, value));


  //If router, send immediatly the pin update
  if (SystemNRF24LPins[indexModule].leaf == 0) {
    ok = nrf_send_digital_out(SystemNRF24LPins[indexModule].RNF24LAddr, OUTPUT, SystemNRF24LPins[indexModule].DigPin[j].pin, value, -1, duration);
    IF_SERIAL_DEBUG_NRF(printf_P(PSTR("DIGITAL OUT PIN HAS BEEN TRASMITTED TO BASE\r\n")));
    //if ok, means that the data has bben trasmited to NODE, so update the vector and send back to APP
    if (ok) {
      SystemNRF24LPins[indexModule].DigPin[j].state = value;
    }
  }
  //LEAF NODE
  else {
    ok = nrf_send_digital_out(SystemNRF24LPins[indexModule].RNF24LAddr, OUTPUT, SystemNRF24LPins[indexModule].DigPin[j].pin, value, -1, duration);     //tx data immediatly
    SystemNRF24LPins[indexModule].DigPin[j].W = true;                                                                               //write request if the LEAF is sleeping
    SystemNRF24LPins[indexModule].DigPin[j].Wstate = value;
    IF_SERIAL_DEBUG_NRF(printf_P(PSTR("DIGITAL OUT PIN WRITE REQUEST HAS BEEN RECORDED\r\n")));
  }




}



void RemoteDigitalSetupNRF24L(uint8_t indexV, byte mode, uint8_t value, bool inv, byte indexModule)                                               //modify the digital pin state (output high or low, or put the buffer in input mode)
{
  bool ok;

  //indexV  2,3,10
  //indexModule: 0,1,2,3

  IF_SERIAL_DEBUG_NRF(printf_P(PSTR("#####################################################################DIGITAL OUT PIN SETUP preparing data for the remote sensor\r\n")));
  IF_SERIAL_DEBUG_NRF(printf_P(PSTR("indexV %d, value:%d, mode:%d, inv:%d, indexModule:%d\r\n"), indexV, value, mode, inv, indexModule));

  short j = json_SearchDigitalPin (NRF24LMaxDigitalPin, SystemNRF24LPins[indexModule].DigPin, indexV, ALL);
  if (j < 0) {
    IF_SERIAL_DEBUG_NRF(printf_P(PSTR("NRF module not found on the list\r\n")));
    return;
  }

  IF_SERIAL_DEBUG_NRF(printf_P(PSTR("Remote pin found: IndexPin:%d, state%d\r\n"), j, value));


  //If router, send immediatly the pin update
  if (SystemNRF24LPins[indexModule].leaf == 0) {
    ok = nrf_send_digital_out(SystemNRF24LPins[indexModule].RNF24LAddr, mode, SystemNRF24LPins[indexModule].DigPin[j].pin, value, SystemNRF24LPins[indexModule].DigPin[j].inv, 0);
    IF_SERIAL_DEBUG_NRF(printf_P(PSTR("DIGITAL SETUP PIN HAS BEEN TRASMITTED TO BASE\r\n")));
    //if ok, means that the data has bben trasmited to NODE, so update the vector and send back to APP
    if (ok) {
      SystemNRF24LPins[indexModule].DigPin[j].state = value;
      SystemNRF24LPins[indexModule].DigPin[j].mode = mode;
      SystemNRF24LPins[indexModule].DigPin[j].inv = inv;
    }
  }
  //LEAF NODE
  else {
    ok = nrf_send_digital_out(SystemNRF24LPins[indexModule].RNF24LAddr, mode, SystemNRF24LPins[indexModule].DigPin[j].pin, value, SystemNRF24LPins[indexModule].DigPin[j].inv, 0);     //tx data immediatly
    SystemNRF24LPins[indexModule].DigPin[j].W = true;                                                                               //write request if the LEAF is sleeping
    SystemNRF24LPins[indexModule].DigPin[j].Wstate = value;
    SystemNRF24LPins[indexModule].DigPin[j].mode = mode;
    SystemNRF24LPins[indexModule].DigPin[j].inv = inv;
    IF_SERIAL_DEBUG_NRF(printf_P(PSTR("DIGITAL SETUP PIN WRITE REQUEST HAS BEEN RECORDED\r\n")));
  }




}




/*
  //search pin in the RF module
  //return the index of the array
  //-1 if it is not found
  short SearchRemoteNRF24LPin (byte index_node, uint8_t port, byte mode_pin) {

  short index_array;
  index_array=json_SearchDigitalPin(NRF24LMaxDigitalPin, SystemNRF24LPins[index_node].DigPin, port, mode_pin);


  return(index_array);

  //short j;
  //for (j = 0; j < NRF24LMaxDigitalPin; j++)  {
  //  if (SystemNRF24LPins[index_node].DigPin[j].mode == mode_pin &&  SystemNRF24LPins[index_node].DigPin[j].used == true  && SystemNRF24LPins[index_node].DigPin[j].pin == port)    //if it is output and is used
  //    return (j);
  }
  return (-1);
  }
*/

//NRF24L Command received from http
//command=0 --  sleep time setting (for each nrf module)   //http://10.0.1.15:8888/IO.json?user=arduino&pass=andrea&cmd=NRF24L&port=0&action=0&action2=60&action3=0&action4=0
//command=1 --  NRF radio enable or disable (NRF base)
//command=2 --  delete all the nodes from the flash list

// RemoteCommandNRF24L(port_i, action_i, action2_i, action3_i, action4_i);
//http://10.0.1.15:8888/IO.json?user=arduino&pass=andrea&cmd=NRF24L&port=1&action=0&action2=0&action3=0&action4=0
void RemoteCommandNRF24L(byte command, unsigned int nrf_module, unsigned int first, unsigned int second, unsigned int third) {

  switch (command) {
    case 0:                                                         //sleep time setting
      SystemNRF24LPins[nrf_module].sleep_time_value = first;
      SystemNRF24LPins[nrf_module].system_back_wr = true;             //write request
      if (!command_from_server_glo) {
        ethbuff_ClientPrint(F("\"nrf_slp\":["));
        ethbuff_ClientPrint(first);
        ethbuff_ClientPrint(F("]"));
      }
      break;
    case 1:             //switch OFF NRF radio system
      if (first > 0) {
        eeprom_write_byteNEW (FLA_NRF_ENABLE_ADDRESS, 0x00);      //NRF ON
        nrf_radio_enable_rq = true;
        nrf_radio_disable_rq = false;
        if (!command_from_server_glo) {
          ethbuff_ClientPrint(F("\"nrf_pwr\":[\"ON\"]"));
        }
      } else
      {
        eeprom_write_byteNEW (FLA_NRF_ENABLE_ADDRESS, 0x55);      //NRF OFF
        nrf_radio_enable_rq = false;
        nrf_radio_disable_rq = true;
        if (!command_from_server_glo) {
          ethbuff_ClientPrint(F("\"nrf_pwr\":[\"OFF\"]"));
        }
      }
      break;
    case 2:                                                       //clear flash node list
      for (byte i = 0; i < NRF24LMaxModules; i++)
        eeprom_write_wordNEW ((FLA_NRF_NODE_ADDRESS + i * 2), 65535);
      if (!command_from_server_glo) {
        ethbuff_ClientPrint(F("\"nrf_eep\":[\"ERA\"]"));
      }
      break;
      //   default:
  }

}
#endif
/*

  //arduino_io --INFO
  //              ANALOGS
  //
  //arduino_var--VARIABLES
  //
  //ardu_sys  -- ardu_date
  //              ardu_fd2
  //              ardu_fd

  //arduino_nrf24l:
  //                  NRF24L_io_0 -- INFO
  //                                  DIGITALS
  //                                  ANALOGS
  //
  //                  NRF24L_var_0-- VARIABLES

  {
  "arduino_io":{"INFO":["3"],"DIGITALS":[["3","pwm","0","0"],["4","out","1","0"],["5","out","0","0"],["6","out","0","0"],["7","out","0","0"],["8","out","0","0"],["9","in","0","0"],["10","out","1","0"],["11","out","0","0"],
  ["12","out","0","0"],["13","out","0","0"],["14","out","0","0"],["15","out","0","0"],["16","out","0","0"],["17","out","0","0"],["18","out","0","0"],["19","out","0","0"],["20","out","0","0"],["21","out","0","0"],["22","in","0","0"],["23","in","0","0"],["24","in","0","0"],["25","in","0","0"],["26","out","0","0"],["27","out","0","0"],["28","out","0","0"],
  ["29","out","0","0"]], "ANALOGS":[2.464,2.416,2.075,1.835,1.739,1.743,1.666,1.532,1.412,1.354,1.321,1.253,1.287,1.239,1.297,1.153]},
  "arduino_var":{"VARIABLES":[52.900,23.600,3.000,3423.000,0.000,0.183,0.289,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000]},

  "NRF24L_io_0":{"INFO":["55381","02","3281","88","344","0","1001","2","0"],"DIGITALS":[],"ANALOGS":[]},
  "NRF24L_var_0":{"VARIABLES":[0.000,0.000,0.000,0.000,55380.000]},

  "ardu_tim":[255,255,255,255,255,255,255,255,255,255,255,255],
  "ardu_sys":{"ardu_date":[0,9,15,33],"ardu_fd2":["XXXX","1111","255.255.255.255","21414"],"ardu_fd":[3,0,0,1,0,0,7.000,7.000]}
  }

  {"arduino_io":
  {"INFO":["1"],"DIGITALS":[["3","in","0","0"],["4","out","0","0"],["5","out","0","0"],["6","out","0","0"],["7","out","0","0"],["8","out","0","0"]]
  ,"ANALOGS":[0.279,0.302,0.334,0.318,0.266,0.230]}
  ,"arduino_var":{"VARIABLES":[0.000,0.000,1.000,2225.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000]}
  ,"NRF24L_io_0":{"INFO":["49518","02","3281","88","346","0","1001","2","0"],"DIGITALS":[["3","in","1","0"],["4","in","1","0"],["5","out","0","0"],["9","out","0","0"]]
  ,"ANALOGS":[1.483,1.077,1.048,0.711]},"NRF24L_var_0":{"VARIABLES":[0.000,0.000,0.000,0.000,49502.000]}
  ,"NRF24L_io_1":{"INFO":["540","012","2873","600","2032","0","1001","2","1"]
  ,"DIGITALS":[["3","in","1","0"],["4","in","1","0"],["5","out","0","0"],["9","out","0","0"]],"ANALOGS":[0.474,0.690,0.920,0.690]}
  ,"NRF24L_var_1":{"VARIABLES":[0.000,0.000,0.000,0.000,539.000]}
  ,"ardu_tim":[255,255,255,255,255,255,255,255,255,255,255,255]
  ,"ardu_sys":{"ardu_date":[6,17,33,11]
  ,"ardu_fd2":["andrea","0000","255.255.255.255","65011"]
  ,"ardu_fd":[1,0,0,2,0,0,8.100,0,0,0,0,0,0]}}



*/
