Translate

domingo, 27 de abril de 2014

Configurando Memória Virtual SWAP no Ubuntu

Quando nosso Sistema Operacional utiliza uma grande porcentagem de memória RAM, para não travar, ele lança mão da Memória Virtual.

Explicando este termo resumidamente, "Memória Virtual" é quando o sistema operacional armazena em disco (acesso mais lento), dados que deveriam ser colocados na memória RAM, e isto não pôde ser feito, porque a mesma já estava muito cheia. 

O fato da memória RAM estar muito cheia pode ser sinal de que seu sistema precisa ser fisicamente atualizado, adicionar mais 'pentes' de memória RAM pode ajudar.

Quando a memória virtual é alocada pelo sistema operacional, o computador se torna mais lento, pois como já disse anteriormente, o acesso aos dados no disco é muito mais lento do que o acesso à memória. 

No Ubuntu, por padrão a memória virtual é acionada quando atinge-se 40% de memória RAM utilizada (60% de memória RAM livre); isto pode tornar o sistema lento rapidamente, no caso do uso mais extremo. 

Para checar como seu Sistema Operacional está usando o recurso de swap (memória virtual) e também a memória em si, execute o comando na janela do Terminal (shell): 

free -m

O resultado deve ser algo parecido com a tela abaixo: 

free -m
             total       used       free     shared    buffers   cached
Mem:          3848       3644        204        263         19      515
-/+ buffers/cache:       3108        740

Swap:         4940        619       4320


Note que meu Sistema operacional, está consumindo 619 MB de memória virtual!

Podemos mudar isto, ajustando o ponto de utilização da memória RAM em que o sistema operacional começará a alocar dados também em Memória Virtual.

Para saber como este ponto está configurado atualmente, digite o seguinte comando :

cat /proc/sys/vm/swappiness 

O SO deve retornar o valor atualmente configurado para swap:

60

O valor a ser alterado é bastante subjetivo, para alterá-lo somente durante a sessão atual como forma de teste, execute o comando: 

sudo sysctl vm.swappiness=30

Verifique que o valor está alterado, chamando novamente:

cat /proc/sys/vm/swappiness 

Para alterá-lo efetivamente no Sistema Operacional, edite com permissão sudo o arquivo /etc/sysctl.conf  e adicione ao final do arquivo a linha: 

vm.swappiness = "VALOR_ESCOLHIDO_ENTRE 0 e 100"

Abaixo exemplo:

sudo gedit /etc/sysctl.conf

Adicionei a este arquivo a linha abaixo, no meu caso o valor de 30, que quer dizer que quando estiver com 70% da RAM ocupada, meu SO irá começar a utilizar Memória Virtual.

vm.swappiness = 30

sábado, 26 de abril de 2014

Enviando E-Mail com Java usando JavaMail e GMail

Eventualmente podemos nos defrontar com a necessidade de que nossas aplicações JAVA enviem E-mails, seja para gerar alertas, seja para rápida comunicação, etc. 

A JavaMail API permite esta implementação de maneira bastante simplificada. 

Juntamente com esta possibilidade, temos uma gigante e poderosa ferramenta de e-mail, gratuita, o Gmail do Google, que nos permite criar uma conta gratuita a fim de integrarmos a mesma à nossa aplicação. 

Os servidores do Gmail, necessitam de uma autenticação um pouco diferenciada (SSL), o que pode se tornar um fator complicador na implementação desta funcionalidade. 

Descrevo neste post uma Classe JAVA que é capaz de enviar emails usando texto simples, ou conteúdo HTML, para uma mensagem mais rebuscada. 

Além disso, realiza a validação e autenticação frente os servidores do Google, de forma a permitir a utilização da mesma com uma conta do Gmail. 

Você ainda pode compilar um .jar da mesma e utilizar seus métodos públicos de envio de e-mail, incorporando facilmente esta funcionalidade a qualquer outra aplicação, sem precisar escrever tudo novamente.


Baixando a JavaMail API

Para começarmos, devemos baixar e adicionar ao nosso classpath (importar o .jar dependendo da IDE) o arquivo java.mail.jar . 


Código Fonte

Abaixo código fonte completo e comentado. O método main()  pode ser usado para executar diretamente a classe no console e enviar mensagens.

Não esqueça de alterar o código com os endereços de remetente e destinatário. 

Para chamá-la através de outras aplicações, simplesmente instancie o construtor EnviaEmail(String, String); com o nome de usuário (cadastrado no Gmail) e senha.




package br.com.devfacil.email.view;

import java.util.Properties;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
 * Classe Utilitária que contém métodos para envio de Email através de conta do
 * Gmail
 */
public class EnviaEmail {

    /**
     * Construtor sem parametros, ao ser chamado já instancia as configuraççoes
     * de email do Gmail na JVM
     *
     */
    public EnviaEmail(String userNameGmail, String senhaGmail) {

        this.username = userNameGmail;
        this.senha = senhaGmail;

        ajustaParametros();

    }

    /**
     * Variavel local para Sessao
     */
    Session session = null;

    String username = null;
    String senha = null;

    /**
     * Metodo 'main()' para teste e execução
     *
     */
    public static void main(String[] args) {

        /**
         * Mensagem de teste para envio de email Html
         */
        String mensagemHtmlTeste = "<html>\n"
                + "<body>\n"
                + "<h1> Mensagem para voc&ecirc;</h1>\n"
                + "<h2> conte&uacute;do da Mensagem:</h2>\n"
                + "<p>Mensagem enviada atrav&eacute;s de Aplica&ccedil;&atilde;o "
                + "que estudei no blog <a href=\"http://www.devfacil.blogspot.com.br\"><b>DevFacil!</b></a></p>\n"
                + "</body>\n"
                + "</html>";

        try {
            EnviaEmail ee = new EnviaEmail("eu@gmail.com", "123456");

            /**
             * Envia mensagem de e-mail com conteúdo html
             */
            ee.enviarEmailHtml("eu@gmail.com", "seu@amigo.com", "Estou aprendendo a Enviar Email através do JAVA!", mensagemHtmlTeste);
            
            /**
             * Envia mensagem de e-mail simples, somente com texto
             */
            ee.enviarEmailHtml("eu@gmail.com", "seu@amigo.com", "Estou aprendendo a Enviar Email através do JAVA!", "Mensagem Somente Texto");

        } catch (Exception ex) {

            System.out.println(ex.getMessage());

        }

    }

    /**
     * Metodo para envio de mensagem com texto simples
     */
    public void enviarEmail(String remetente, String destinatario, String assunto, String conteudo) throws Exception {

        try {

            Message message = new MimeMessage(session);

            //Configura o Remetente da mensagem
            message.setFrom(new InternetAddress(remetente));

            //Configura o Destinatário da mensagem
            Address[] toUser = InternetAddress
                    .parse(destinatario);

            //Configura o Assunto da mensagem
            message.setRecipients(Message.RecipientType.TO, toUser);
            message.setSubject(assunto);

            //Configura o Conteudo da mensagem
            message.setText(conteudo);

            /**
             * Envia a mensagem criada
             */
            Transport.send(message);

            System.out.println("Email enviado com Sucesso; ");

        } catch (MessagingException e) {
            throw new Exception("Erro ao enviar email! \n" + e.getMessage());
        }

    }

    /**
     * Metodo para envio de mensagem padrao HTML ja formatado
     */
    public void enviarEmailHtml(String remetente, String destinatario, String assunto, String conteudoHtml) throws Exception {
        try {

            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(remetente));

            Address[] toUser = InternetAddress
                    .parse(destinatario);

            message.setRecipients(Message.RecipientType.TO, toUser);
            message.setSubject(assunto);

            Multipart multipart = new MimeMultipart("related");
            BodyPart htmlPart = new MimeBodyPart();
            htmlPart.setContent(conteudoHtml, "text/html");

            multipart.addBodyPart(htmlPart);

            message.setContent(multipart);

            /**
             * Método para enviar a mensagem criada
             */
            Transport.send(message);

            System.out.println("Email enviado com Sucesso; ");

        } catch (MessagingException e) {
            throw new Exception("Erro ao enviar email! \n" + e.getMessage());
        }

    }

    /**
     * Configura aa propriedades da JVM com parametros do servidor Gmail
     *
     * Modificador de acesso 'private' pois não é necessário que este método
     * seja chamado de outras classes
     */
    private void ajustaParametros() {

        Properties props = new Properties();

        /**
         * Conexão com servidor Gmail
         */
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");

        /**
         * Associa autenticação a sessao de correio
         */
        session = Session.getDefaultInstance(props,
                new javax.mail.Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(username, senha);
                    }
                });

    }

}

quinta-feira, 24 de abril de 2014

Jogo Simon com Arduino

No Brasil conhecido como 'Genius', sucesso na década de 80. 

Jogo simples, com memória de melhor jogada e contagem de pontos. 

Vídeo demonstrativo abaixo:







Pressione qualquer tecla e mantenha pressionada até que o computador faça a jogada. Repita a jogada o quanto puder. A jogada mais extensa é gravada na EEPROM e  exibida como recorde no LCD. 

Para Limpar a memoria, pressione as chaves 0 e 4 (as das extremidades) e, mantendo-as pressionadas, reinicie o Arduino, ate ouvir um beep e  aparecer a mensagem de limpeza da memoria. 

Abaixo o código, com métodos de som (utilizando buzzer). 



Led's ligados às saídas A0 ~ A3 (constantes no código 14 aé 17)  e chaves ligadas às entradas 6 ~ 9 (constantes no código 6 até 9); 


Abaixo, diagrama de ligação: 




Código Fonte:



/*

Jogo Simon para Arduino

Para iniciar, pressione e matenha pressionada qualquer tecla. 

Para recomeçar pressione RESET

Para Limpar a memoria, pressione e mantenha pressionada as teclas
1 e 4, ate ouvir o beep.


*/


//Adiciona biblioteca para Cristal Liquido
#include <LiquidCrystal.h>

//Adiciona biblioteca para EEPROM
#include <EEPROM.h>


//Configura pinos ligados ao display LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//Quantidade de jogadas maxima
const int JOGADAS_SIZE = 100;


//Velocidade dos leds durante exibicao inicial
const int DELAY_APRESENTACAO = 150;
//
//Teclas
const int key1 = 6; 
const int key2 = 7;
const int key3 = 8;
const int key4 = 9; 
//
//Leds
const int led1 = A0; //14
const int led2 = A1; //15
const int led3 = A2; //16
const int led4 = A3; //17
//
//Pino ligado ao Buzzer
const int pin10 = 10;
//
//Tons emitidos pelo buzzer
const int som1 = 50;
const int som2 = 100;
const int som3 = 150;
const int som4 = 200;
//
//Vetor de jogadas do computador
int cpu[JOGADAS_SIZE]; //quantidade de jogadas
int tempoNivel = 250;  //velocidade do jogo
//Variave de controle da jogada atual
int jogadaAtual = 0;
//Recorde
int recorde = 0; 
//
boolean resultado = true; 
//  -led in 17 key 4  //ligacao das teclas e saidas (led e teclas)
//  -led in 16 key 3
//  -led in 15 key 1
//  -led in 14 key 1

//

void setup(){


  Serial.begin(9600);
  lcd.begin(16, 2);
  pinMode(key1, INPUT);
  pinMode(key2, INPUT);
  pinMode(key3, INPUT);
  pinMode(key4, INPUT);
  //
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  //
  pinMode(10, OUTPUT);

  limpaMemoria();

  //
  // como a entrada analogica 5 nao esta conectada
  // o ruido vai fazer com que o metodo
  // randomSeed(), que inicializa o gerador
  // de numeros pseudo-aleatorios da funcao random()
  randomSeed(analogRead(5)); 


  carregaRecorde();

  preencheVetor();
  escreveVetor();

  apresenta();

}

void loop(){

  escreveLcd();
  jogadaCpu(); 

  resultado= lerTeclado(); 

  if(resultado == false){

    lcd.setCursor(0, 1);
    lcd.print("Voce Falhou"); 

    checaRecorde();

    errou();

  }
  else{
    
    delay(1000);
    
  };

}

void limpaMemoria(){

  if(digitalRead(key1)
    && digitalRead(key4)){

    digitalWrite(pin10, HIGH);
    delay(50);
    digitalWrite(pin10,LOW);
    lcd.clear();
    lcd.print("Limpando Memor..");

    for (int i = 0; i < 512; i++)
      EEPROM.write(i, 0);

    digitalWrite(pin10, HIGH);
    lcd.clear();
    lcd.print("Memoria Limpa!");
    delay(2000);
    digitalWrite(pin10,LOW);
  }


}

void carregaRecorde(){

  recorde = EEPROM.read(0);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("Recorde: "); 
  lcd.setCursor(11, 1);
  lcd.print(recorde); 
}

void checaRecorde(){

  if(jogadaAtual > recorde){

    recorde = jogadaAtual; 
    EEPROM.write(0, recorde);

    lcd.clear(); 
    lcd.setCursor(0,0);
    lcd.print("Novo Recorde");

    lcd.setCursor(14,0);
    lcd.print(recorde);

  }

}

void somOn(int s){

  switch(s){

  case 14:
    analogWrite(pin10, som1);
    break;


  case 15:
    analogWrite(pin10, som2);
    break;


  case 16:
    analogWrite(pin10, som3);
    break;



  case 17:
    analogWrite(pin10, som4);
    break;
  }

}

void somOff(){

  analogWrite(pin10, 0); 

}

void jogadaCpu(){

  for(int j = 0; j<=jogadaAtual; j++){
    somOff();
    digitalWrite(cpu[j], LOW);
    delay(tempoNivel);     
    digitalWrite(cpu[j], HIGH);
    somOn(cpu[j]);
    delay(tempoNivel); 
    digitalWrite(cpu[j], LOW);
    somOff();
  }

}

void preencheVetor(){

  for(int x = 0; x < JOGADAS_SIZE; x++){

    cpu[x] = random(14,18);

  }

}

void escreveVetor(){

  for(int x = 0; x < JOGADAS_SIZE; x++){

    Serial.print(cpu[x]);
    Serial.print(" - ");
  }
  Serial.print("\n");

}

void errou(){

  analogWrite(pin10, 50);
  delay(500);
  analogWrite(pin10, 40);

  delay(500);            
  analogWrite(pin10, 30);
  delay(500);
  analogWrite(pin10, 20);
  delay(1000);
  somOff();

  while(true){
    delay(DELAY_APRESENTACAO);
    digitalWrite(14, HIGH);
    digitalWrite(15, HIGH);
    digitalWrite(16, HIGH);
    digitalWrite(17, HIGH);
    delay(DELAY_APRESENTACAO);  

    digitalWrite(14, LOW);
    digitalWrite(15, LOW);
    digitalWrite(16, LOW);
    digitalWrite(17, LOW);
    delay(DELAY_APRESENTACAO);
  }

}

void apresenta(){


  while(true){

    if(digitalRead(key1)
      ||digitalRead(key2)
      ||digitalRead(key3)
      ||digitalRead(key4)){
      delay(150);
      if(!digitalRead(key1)
        ||!digitalRead(key2)
        ||!digitalRead(key3)
        ||!digitalRead(key4)){
        return;
      }
    }
    delay(DELAY_APRESENTACAO * 2);
    for(int i = 14; i<=17; i++){
      digitalWrite(i, HIGH);
      delay(DELAY_APRESENTACAO);
    } 

    for(int i = 14; i<=17; i++){
      digitalWrite(i, LOW);
      delay(DELAY_APRESENTACAO);
    } 

    delay(DELAY_APRESENTACAO * 2);

    for(int i = 17; i>=14; i--){
      digitalWrite(i, HIGH);
      delay(DELAY_APRESENTACAO);
    } 

    for(int i = 17; i>=14; i--){
      digitalWrite(i, LOW);
      delay(DELAY_APRESENTACAO);
    } 
    delay(DELAY_APRESENTACAO * 2);
  }
}

boolean lerTeclado(){

  int index = 0;
  int jogadaPlayer = 0; 
  boolean jogou = false;

  do{
    do{
      jogou = false;

      while(digitalRead(key1)){
        delay(150);
        digitalWrite(14,HIGH); 
        somOn(14);
        if(!digitalRead(key1)){

          delay(150); 
          digitalWrite(14,LOW); 
          somOff();
          jogadaPlayer = 14;
          jogou = true;

          Serial.print(jogadaPlayer) ; 
          Serial.print("-"); 

        }
      }


      while(digitalRead(key2)){
        delay(150);
        digitalWrite(15,HIGH); 
        somOn(15);
        if(!digitalRead(key2)){

          delay(150); 
          digitalWrite(15,LOW);
          somOff();
          jogadaPlayer = 15;
          jogou = true;

          Serial.print(jogadaPlayer) ; 
          Serial.print("-"); 

        }
      }
      while(digitalRead(key3)){ 
        delay(150);
        digitalWrite(16,HIGH); 
        somOn(16);
        if(!digitalRead(key3)){

          delay(150); 
          digitalWrite(16,LOW);
          somOff();
          jogadaPlayer = 16;
          jogou = true;

          Serial.print(jogadaPlayer) ; 
          Serial.print("-"); 

        }
      }
      while(digitalRead(key4)){
        delay(150);
        digitalWrite(17,HIGH); 
        somOn(17);
        if(!digitalRead(key4)){

          delay(150); 
          digitalWrite(17,LOW);
          somOff();
          jogadaPlayer = 17;
          jogou = true;

          Serial.print(jogadaPlayer) ; 
          Serial.print("-"); 

        }
      }
    }
    while(jogadaPlayer == 0); 
    if(cpu[index] != jogadaPlayer){
      Serial.print(cpu[index]);
      Serial.print(jogadaPlayer);
      return false; 

    }

    jogadaPlayer = 0; 
    index++;
  }
  while(index<=jogadaAtual); 
  jogadaAtual++;
  Serial.print("\n");

  tempoNivel = tempoNivel-10; //torna o jogo mais rapido

  return true; 
}

void escreveLcd(){
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Pontos: ");
  lcd.setCursor(13,0);
  lcd.print(jogadaAtual);

}

Bom divertimento!

quarta-feira, 23 de abril de 2014

Wrapper e Primitivos, quando utilizar?

Os tipos de uma varável em JAVA (uma linguagem fortemente "tipada") são fundamentais no código e devem ser escolhidos com cautela, analisando sempre o que cada variável deve representar, seja para a lógica de negócio da aplicação, seja para variáveis de controle de fluxo do código. 

Os tipos primitivos, já são de conhecimento da maioria dos programadores e são exibidos na tabela abaixo: 



As classes Wrapper nada mais são (em linhas gerais) do que uma Classe, que "representa um primitivo", desta forma, uma variável de um tipo Wrapper pode ser null e pode ser instanciada (na memória) ou não (quando possui valor nulo). 

É fácil localizarmos as Classes Wrapper, que possuem os mesmos nomes dos tipos primitivos, somente com a primeira letra maiúscula. 

O Java nos oferece Classes Wrapper para todos os tipos primitivos. Assim sendo, todas linhas de código abaixo são válidas. 

        Byte b = null; 
        Short s = null; 
        Integer i = null; 
        Long l = null; 
        Float f = null; 
        Double d = null;
        Character c = null; 
        Boolean bol = null;


Além de possuir diversos métodos para trabalharmos com os primitivos que ela representa, ela nos oferece dois construtores, um recebendo como parametro um valor do tipo primitivo que ela representa 
Integer inteiro = new Integer(10); 
 
e outra recebendo uma String que é convertida para o valor primitivo que a classe Wrapper representa, 

Integer inteiroStr = new Integer("10"); 
 
Uma das necessidades de se utilizar um Wrapper, ao invés de um primitivo, é construtores de classes de algumas API (Collections por exemplo) não suportam tipos primitivos.  O código abaixo, por exemplo, não compila:


    List<int> lista = new ArrayList<int>();

O correto, seria utilizar Wrapper:


    List<Integer> lista = new ArrayList<Integer>();

Autoboxing

Um objeto Integer pode receber um primitivo diretamente, através do Autoboxing:

  Integer i = 15; 


Ou ainda:

    int inteiroPrimitivo = 15; 
        
    Integer k = inteiroPrimitivo; 
        

Ou ainda, nossa lista de Integer pode receber diretamente um valor primitivo, ou usando o construtor recebendo uma String como parâmetro:

    List<int> lista = new ArrayList<int>();

    lista.add(15);
    lista.add(new Integer("40"));


Unboxing

Abaixo, exemplos de Unboxing explícitos e implícitos (automáticos):

 

        int i = 10;

        Integer inteiroWrapper = new Integer(i);  // Boxing Explicito
        int k = inteiroWrapper.intValue();        // Unboxing Explicito

        inteiroWrapper = i; // Boxing Automatico
        k = inteiroWrapper; // Unboxig Automatico


Resumindo, o procedimento de Boxing converte um valor primitivo numa referência do seu correspondente Wrapper (Integer), já no procedimento de Unboxing, a referencia é transformada no tipo primitivo correspondente. 

Abaixo exemplos de outras conversões: 

 
        boolean boolValor = true;
        byte b = 2;
        short s = 2;
        char c = '2';
        int i = 2;

        // Boxing
        Boolean boolReferencia = boolValor;
        Byte bReferencia = 88;
        Short sReferencia = 2;
        Character cReferencia = '2';
        Integer iReferencia = 2;
       // Integer iRef1 = s; // ATENÇÂO!! tipos short não podem ser associados a Integer

        // Unboxing
        boolean boolVal1 = boolReferencia;
        byte b1 = bReferencia;
        short s1 = sReferencia;
        char c1 = cReferencia;
        int i1 = iReferencia;

terça-feira, 15 de abril de 2014

Sistemas Embarcados - Arduino

Palestra UNIFEG (15/03/2014) - Sistemas Embarcados, Arduino


Aproveitando o blog, para postar a apresentação da palestra ministrada no Centro Universitário Fundação Educacional de Ensino de Guaxupé/MG (UNIFEG), sobre Sistemas Embarcados com ênfase na Plataforma Arduino.
Texto bastante básico e explicativo, para que os alunos tivessem o primeiro contato com a plataforma.


segunda-feira, 14 de abril de 2014

Alterando senha SUDO Linux

Este é daqueles comandos que as vezes nos esquecemos e nos fazem falta. 

Para alterar a senha sudo em ambiente Linux abra a janela do Terminal e execute o seguinte comando: 


~$ sudo passwd seu_nome_de_usuario_aqui

Ser á solicitada a nova senha:


Enter new UNIX password: 

Digite e será solicitado que repita a senha:


Retype new UNIX password:

Ao redigitar é exibida a mensagem abaixo e a senha sudo está atualizada!
passwd: password updated successfully

domingo, 13 de abril de 2014

Tutorial Integração Spring Framework e Quartz

Artigo


Agendando Tarefas Utilizando Quartz e Spring Framework


Ano passado, fui convidado pela equipe da Easy Java Magazine a escrever este artigo, que trata sobre como integrar as bibliotecas do agendador de tarefas Quartz em aplicações que utilizem o Spring Framework.

Abaixo o link direto para a página da matéria que saiu na revista Easy Java Magazine #25:


Ler Artigo no Site da Revista