int GCodeProcessor::execute(Command* command) {
	if(command == NULL || command->getCodeEnum() == CODE_UNDEFINED) {
		if(LOGGING) {
			printCommandLog(command);
		}
		return -1;
	}
	GCodeHandler* handler = getGCodeHandler(command->getCodeEnum());
	if(handler == NULL) {
		Serial.println("This is false: handler == NULL");
		return -1;
	}
	Serial.println(COMM_REPORT_CMD_START);
	int execution = handler->execute(command);
	if(execution == 0) {
		Serial.println(COMM_REPORT_CMD_DONE);
	} else {
		Serial.println(COMM_REPORT_CMD_ERROR);
	}
	return execution;
};
int GCodeProcessor::execute(Command *command)
{

  int execution = 0;
  bool isMovement = false;

  bool emergencyStop = false;
  emergencyStop = CurrentState::getInstance()->isEmergencyStop();

  int attempt = 0;
  int maximumAttempts = ParameterList::getInstance()->getValue(PARAM_MOV_NR_RETRY);

  long Q = command->getQ();
  CurrentState::getInstance()->setQ(Q);

  if
  (
    command->getCodeEnum() == G00 ||
    command->getCodeEnum() == G01 ||
    command->getCodeEnum() == F11 ||
    command->getCodeEnum() == F12 ||
    command->getCodeEnum() == F13 ||
    command->getCodeEnum() == F14 ||
    command->getCodeEnum() == F15 ||
    command->getCodeEnum() == F16
  )
  {
    isMovement = true;
  }



  //Only allow reset of emergency stop when emergency stop is engaged

  if (emergencyStop)
  {
    if (!(
      command->getCodeEnum() == F09 ||
      command->getCodeEnum() == F20 ||
      command->getCodeEnum() == F21 ||
      command->getCodeEnum() == F22 ||
      command->getCodeEnum() == F81 ||
      command->getCodeEnum() == F82 ||
      command->getCodeEnum() == F83 ))
    {

    Serial.print(COMM_REPORT_EMERGENCY_STOP);
    CurrentState::getInstance()->printQAndNewLine();
    return -1;
    }
  }

  // Do not execute the command when the config complete parameter is not
  // set by the raspberry pi and it's asked to do a move command

  if (ParameterList::getInstance()->getValue(PARAM_CONFIG_OK) != 1)
  {
    if (isMovement)
    {
      Serial.print(COMM_REPORT_NO_CONFIG);
      CurrentState::getInstance()->printQAndNewLine();
      return -1;
    }
  }

  // Return error when no command or invalid command is found

  if (command == NULL)
  {

    Serial.print(COMM_REPORT_BAD_CMD);
    CurrentState::getInstance()->printQAndNewLine();

    if (LOGGING)
    {
      printCommandLog(command);
    }
    return -1;
  }

  if (command->getCodeEnum() == CODE_UNDEFINED)
  {
    Serial.print(COMM_REPORT_BAD_CMD);
    CurrentState::getInstance()->printQAndNewLine();

    if (LOGGING)
    {
      printCommandLog(command);
    }
    return -1;
  }

  // Get the right handler for this command

  GCodeHandler *handler = getGCodeHandler(command->getCodeEnum());

  if (handler == NULL)
  {
    Serial.print(COMM_REPORT_BAD_CMD);
    CurrentState::getInstance()->printQAndNewLine();

    Serial.println("R99 handler == NULL\r\n");
    return -1;
  }

  // Report start of command

  Serial.print(COMM_REPORT_CMD_START);
  CurrentState::getInstance()->printQAndNewLine();

  // Execute command with retry
  CurrentState::getInstance()->setLastError(0);
  while (attempt < 1 || (!emergencyStop && attempt < maximumAttempts && execution != 0 && execution != 2))
  // error 2 is timeout error: stop movement retries
  {

    if (LOGGING || debugMessages)
    {
      Serial.print("R99 attempt ");
      Serial.print(attempt);
      Serial.print(" from ");
      Serial.print(maximumAttempts);
      Serial.print("\r\n");
    }

    attempt++;
    if (attempt > 1)
    {
      Serial.print(COMM_REPORT_CMD_RETRY);
      CurrentState::getInstance()->printQAndNewLine();
    }
    
    handler->execute(command);
    execution = CurrentState::getInstance()->getLastError();
    emergencyStop = CurrentState::getInstance()->isEmergencyStop();

    if (LOGGING || debugMessages)
    {
      Serial.print("R99 execution ");
      Serial.print(execution);
      Serial.print("\r\n");
    }
  }

  // Clean serial buffer
  while (Serial.available() > 0)
  {
    Serial.read();
  }

  // if movemement failed after retry
  // and parameter for emergency stop is set
  // set the emergency stop

  if (execution != 0)
  {
    if (isMovement)
    {
      if (ParameterList::getInstance()->getValue(PARAM_E_STOP_ON_MOV_ERR) == 1)
      {
        CurrentState::getInstance()->setEmergencyStop();
      }
    }
  }

  // Report back result of execution
  if (execution == 0)
  {
    Serial.print(COMM_REPORT_CMD_DONE);
    CurrentState::getInstance()->printQAndNewLine();
  }
  else
  {
    Serial.print(COMM_REPORT_CMD_ERROR);
    CurrentState::getInstance()->printQAndNewLine();
  }

  CurrentState::getInstance()->resetQ();
  return execution;
};