Arduino stops sending info to server after a while

and here is the ino file too:

#include <SMS_3G.h> //For sms, it's actually with cosm that it will be sent!
#include <TCP_3G.h>

SMS_3G sms;  //As there are no arguments, drop the brackets
TCP_3G info;
char phone_number[]="*********"; //is the number to which the SMS is going to bo sent
int once = 0; //used to send the only once an sms telling the user 22 bottles are filled

// Pin number of the sensor's output:
const int pingPin = 7;
const int iscoPin = 9;

// Time
unsigned int dtLoop = 10000;            // [ms]
double dtCstSampling = 60.0;           // [s]
double nextSampleTime = 0;             // [s]

// Sensor (height in [cm])
const int dhStormThr = 2;              // [cm/s] for Chambrone a good threasold would be 5-8 cm/jour
const double dhRecPercThr = 0.1;       // [%] recesion detcted when height 10% lower than peak height
float hBase = 0.0f;                    // The mean distance between the senseor and the water.
float cm = 0.0f, cmPeak = -10000.0f;   // The height of the water relative to 'hBase': cm = sensor value - hBase.

// Lowpass filter of the sensor data: alpha with dT_ech and dT_filtre
unsigned int dtFilter = 5000;          // [ms]
const float alpha = (dtLoop/1000.0f) / ((dtFilter/1000.0f)/(2.0f*3.14159f)+(dtLoop/1000.0f));

// Model parameters
double c = 1.0/5.0;                    // in [1/seconds]

// Sampler
unsigned const char nbBottles = 24;    // Total number of bottles in the sampler.
unsigned const char stockBottles = 2;  // Bottles that should remain after the flood.
unsigned char curBottle = 1;           // The current bottle waiting to be filled.

// State of the sensor, because we need to calibrate it (to initialize the hBase variable).
typedef enum {
  CALIGBRATING, SENSOR_READY} 
SensorState;
SensorState sensorState;

// State of river
typedef enum {
  WAIT_STORM, WAIT_RECESSION, RECESSION, SAMPLER_FULL} 
StormState;
StormState stormState;

// State of sampling
typedef enum {
  NOT_SAMPLING, CST_SAMPLING, PROG_SAMPLING} 
SamplingState;
SamplingState samplingState;

void setup()
{
  // initialize serial communication.
  Serial.begin(115200);

  // initialize ISCO command pin
  pinMode(iscoPin, OUTPUT);
  digitalWrite(iscoPin, LOW);

  // initialize the SMS and the TCP connection
  // Don't call switchmodule twice!
  sms.begin(13, 2);
  info.begin(13 ,2);

  // initialize states.
  sensorState = CALIGBRATING;
  stormState = WAIT_STORM;
  samplingState = NOT_SAMPLING;
  //Serial.println("Calbrating");
}

void loop()
{
  long duration = getDistancePulseDuration();             // get the datat from the Ultrasound sensor.
  float sensorCM = microsecondsToCentimeters(duration);   // convert the time into a distance
  if(sensorState == CALIGBRATING) { // Calibrate the sensor -> the base height is the current height.
    calibrateSensor(sensorCM);
    return;
  }

  float cmCur, cmDerivative, dhRecThr;
  cmCur = hBase - sensorCM;
  cmDerivative = cm; // store prev_val here to save the number of variables
  cm = alpha*cmCur + (1.0f-alpha)*cm;
  cmDerivative = (cm - cmDerivative) / float(dtLoop / 1000.f);

  // Storm state management
  // (WAIT_STORM -> WAIT_RECESSION (10% of height peak) -> RECESSION -> WAIT_STORM).
  switch(stormState) {

  case WAIT_STORM: // Waiting for the flood.
    if(cmDerivative > dhStormThr) { // The flood is detected when slope of height curve overcome dhStormThr.
      stormState = WAIT_RECESSION;
      samplingState = CST_SAMPLING; 
    }
    break;

  case WAIT_RECESSION: // Waiting that the height of water decrease.
    cmPeak = cm > cmPeak ? cm : cmPeak;
    dhRecThr = cmPeak * dhRecPercThr;
    if(cmPeak - cm > dhRecThr) { // Check if height of water is under dhRecPercThr [%] of the highest water height value.
      cmPeak = -10000.0f;
      stormState = RECESSION;
      samplingState = PROG_SAMPLING;
    }
    break;

  case RECESSION: // In recession, waiting that all the bottles are empty.
    if(curBottle > nbBottles-stockBottles) { // We preserve some bottles in case...
      if(once == 0){
		//-----------------------------------------------------
        // send SMS to operator
        //-----------------------------------------------------
        sms.sendSMS(phone_number, "finished sampling, two bottles left in case");
        once++;
      }
      stormState = WAIT_STORM;
      samplingState = NOT_SAMPLING;
    }
    else if(cmDerivative > dhStormThr) { // A flood is detected during the recetion -> go back to constant sampling and wait for recession.
      stormState = WAIT_RECESSION;
      samplingState = CST_SAMPLING; 
    }
    break; 
  }

  // Sampling management. 
  if(samplingState != NOT_SAMPLING) { // We are sampling.
    double remainingTime = nextSampleTime - double(millis())/1000.0;
    if(remainingTime < 0.0) { // next sample
      
      /*if(curBottle == 1) {
        // SMS sent to say the sampling has started 
        //sms.sendSMS(phone_number, "Sampling started");
        //Serial.println("first SMS sent.");
      }*/
      curBottle++;
      if(curBottle >= nbBottles) { // sampler full -> send SMS
        //-----------------------------------------------------
        // send SMS to operator
        //-----------------------------------------------------
        samplingState = NOT_SAMPLING;
        stormState = SAMPLER_FULL;
        //sms.sendSMS(phone_number, "Sampler full, the prediction might have been wrong, or the sampling's totally finished");
        //Serial.println("SMS sent.");
      }
      else {
        //-----------------------------------------------------
        // send next sample cammand to ISCO Sampler
        digitalWrite(iscoPin, HIGH);
        delay(10);
        digitalWrite(iscoPin, LOW);
        //-----------------------------------------------------
        if(samplingState == CST_SAMPLING) {
          nextSampleTime = computeNextSampleCstTime(dtCstSampling);
        }
        else {
          nextSampleTime = computeNextSampleProgTime(curBottle, nbBottles, c);
        }
      }
    }
  }
  info.sendInfo(curBottle, cm, cmDerivative); //We send info every time

    delay(dtLoop);
}



void calibrateSensor(float height) {
  int dt = 100;
  const float a = (dt/1000.0f) / ((2000.0f/1000.0f)/(2.0f*3.14159f)+(dt/1000.0f));
  hBase = a*height + (1.0f-a)*hBase;
  delay(dt);
  if(millis() > 5000) // we calibrate sensor during 2s.
    sensorState = SENSOR_READY;
}


double computeNextSampleCstTime(double dtCstSampling) {
  return dtCstSampling + double(millis())/1000.0;
}


double computeNextSampleProgTime(unsigned char a, unsigned char RS, float c) {
  // The time between samples is computed such that each sampling interval correspond
  // to an equal volume of flow under the predicated hydrograph recession curve.
  double t_sample = (exp( 2.996*double(a) / double(RS)) - 1.0f) / double(c);
  t_sample += double(millis())/1000.0;
  return t_sample;
}


long getDistancePulseDuration()
{
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH pulse whose duration is the
  // time (in microseconds) from the sending of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  return pulseIn(pingPin, HIGH);
}


float microsecondsToCentimeters(long microseconds)
{
  // The speed of sound is 343.2 m/s or 29.1375 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the object we take half of the distance travelled.
  return microseconds / 2.0f / 29.1375f;
}