Ir ao conteúdo
  • Cadastre-se
Lucas Scheunemann

C++ Como enviar comando para porta USB em C++

Recommended Posts

Olá,

Seguinte, tenho uma placa com vários leds, tenho também um software de testes desta placa, neste programa eu informo o comando (uma sequencia de 8 caracteres) e ele acende o led do respectivo comando. O que eu quero é que meu programa faça exatamente o que este software de testes faz, quero informar o sequencia de caracteres para a placa a partir do meu programa. A placa utiliza comunicação USB, consegui reconhecer a porta USB que esta conectada no meu programa, só não consigo enviar o comando, segue abaixo o código que apenas reconhece se a placa está conectada. Agradeço muito se alguém pude me ajudar.

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
  DCB dcb;
  HANDLE hCom;
  BOOL fSuccess;
  char *pcCommPort = "COM6";

  hCom = CreateFile( pcCommPort,
					 GENERIC_READ | GENERIC_WRITE,
					 0,	// comm devices must be opened w/exclusive-access
					 NULL, // no security attributes
					 OPEN_EXISTING, // comm devices must use OPEN_EXISTING
					 0,	// not overlapped I/O
					 NULL  // hTemplate must be NULL for comm devices
					 );

  if (hCom == INVALID_HANDLE_VALUE) {
	  // Handle the error.
	  printf ("CreateFile failed with error %d.\n", GetLastError());
	  return (1);
	}

  // We will build on the current configuration, and skip setting the size
  // of the input and output buffers with SetupComm.

  fSuccess = GetCommState(hCom, &dcb);

  if (!fSuccess) {
	  // Handle the error.
	  printf ("GetCommState failed with error %d.\n", GetLastError());
	  return (2);
	}

  // Fill in the DCB: baud=57,600 bps, 8 data bits, no parity, and 1 stop bit.

  dcb.BaudRate = CBR_57600;	 // set the baud rate
  dcb.ByteSize = 8;			 // data size, xmit, and rcv
  dcb.Parity = NOPARITY;		// no parity bit
  dcb.StopBits = ONESTOPBIT;	// one stop bit

  fSuccess = SetCommState(hCom, &dcb);

  if (!fSuccess) {
	  // Handle the error.
	  printf ("SetCommState failed with error %d.\n", GetLastError());
	  return (3);
	}

  printf ("Serial port %s successfully reconfigured.\n", pcCommPort);
   /// AQUI PRECISO ENVIAR A SEQUENCIA DE CARACTERES PARA A PLACA //////////
  return (0);
}

 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

E ai cara, primeira coisa !

Citação

 tenho uma placa com vários leds

Qual o nome/modelo da placa ? Você precisa ter acesso ao manual/arquitetura da placa, no manual da placa deve ter todos os comandos que geralmente são em hexadecimal que determina quais funções do Firmware da placa são executados/acessados conforme o hexcode que você envia. "Geralmente" a placa faz alguma operação quando você criar/envia um "pacote completo" com checksum etc ... você precisa ver no manual qual é o formato de pacote válido que a placa aceita e isso para cada porta, os formatos de pacote podem variar conforme a porta, e também precisa saber qual é o tipo de retorno de cada porta conforme o hexcode enviado, por exemplo, você envia um pacote de 8 bits na COM6, aí vai estar no manual que para este pacote recebe-se um ponteiro de char, desta forma se você não souber previamente os tipos de retorno terá erros em tempo de execução. Junto desse manual geralmente você terá acesso a arquitetura da placa, nela está indicada as suas funções, suas portas, tudo bem detalhado. Ja é um bom passo acessar/detectar que a porta está ON, mas pra conversar com a placa pelo teu programa vai dar mais trabalho, você vai perder um tempinho brincando com isso ai. Existem alguns programas que só montam e enviam pacotes em portas COM, antes de você criar o pacote em C++, você pode montar pacotes e enviar para a porta, pra ver o que ela retorna, quando estiver OK, você só monta o pacote em C++, mas ja vai saber que o pacote esta em um formato válido, isso facilita, e vai evitar de você compilar o teu programa trocentas vezes, e ficar na dúvida se quem esta errado é o código ou o pacote enviado.

Citação

DICA do mal ...

Se você não tiver o manual você pode tentar "ficar escutando" os pacotes que a porta recebe e envia com o teu software que já esta funcionando corretamente, se a placa aceitar cabo de rede você pode usar o Wireshark pra fazer isso, caso contrário ache uma alternativa para as portas COM. Assim pode descobrir qual o tipo de pacote, tipos de retorno, formatos de pacote que a placa recebe, baseado nisto você tem como montar pacotes válidos no teu programa e enviar para a placa ... Mas isso é gambiarra e da muito mais trabalho e dor de cabeça, você deve ter o manual ...

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Plástico Bolha Então, primeiramente muito obrigado pelas dicas.

Assim: é uma placa controladora de uma torre de sinalização, no manual só diz a sequencia de bytes que preciso enviar para acender determinado led.

Enfim, eu sei a sequencia que preciso enviar para a placa, só não sei COMO enviar através do me sistema, se tiver algum exemplo, pode ser em qualquer linguagem, agradeço muito.

Tenho o software de testes da placa, que se eu digitar, por exemplo a sequência C6120100 acende o led verde. Gostaria de saber como enviar esta sequência através do meu software.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Em 30/01/2018 às 17:13, Lucas Scheunemann disse:

@Plástico Bolha Então, primeiramente muito obrigado pelas dicas.

Assim: é uma placa controladora de uma torre de sinalização, no manual só diz a sequencia de bytes que preciso enviar para acender determinado led.

Enfim, eu sei a sequencia que preciso enviar para a placa, só não sei COMO enviar através do me sistema, se tiver algum exemplo, pode ser em qualquer linguagem, agradeço muito.

Tenho o software de testes da placa, que se eu digitar, por exemplo a sequência C6120100 acende o led verde. Gostaria de saber como enviar esta sequência através do meu software.

Cara eu posso até colocar aqui uma implementação em JAVA que tenho de comunicação com equipamentos externos ... Provavelmente não vai te ajudar muito, a menos que você estude o código ... Vou enviar um trechos de código relevantes da comunicação

package comunication.serial;


import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import org.apache.log4j.Logger;

/**
 *
 * Classe de comunicação com equipamento via porta Serial.
 *
 */
public class ExecuteSerialComm implements SerialPortEventListener {

    //constantes
    public static final int PARITY_NONE = SerialPort.PARITY_NONE;
    public static final int PARITY_MARK = SerialPort.PARITY_MARK;
    public static final int PARITY_SPACE = SerialPort.PARITY_SPACE;
    public static final int STOPBITS_1 = SerialPort.STOPBITS_1;
    public static final int STOPBITS_1_5 = SerialPort.STOPBITS_1_5;
    public static final int STOPBITS_2 = SerialPort.STOPBITS_1;
    public static final int DATABITS_5 = SerialPort.DATABITS_5;
    public static final int DATABITS_6 = SerialPort.DATABITS_6;
    public static final int DATABITS_7 = SerialPort.DATABITS_7;
    public static final int DATABITS_8 = SerialPort.DATABITS_8;
    public static final int v9600 = 9600;
    public static final int v19200 = 19200;
    public static final int v57600 = 57600;
    public static final int v115200 = 115200;
    //variáveis da classe
    private int baudrate;               //velocidade da comunicação
    private CommPortIdentifier cp;      //Identificador da porta serial
    private SerialPort port;            //porta serial
    private OutputStream input;         //buffer se saída
    private InputStream output;         //buffer de entrada
    private boolean write;              //flag para leitura
    private boolean read;               //flag para escrita
    private String strPorts;            //Porta com no formato String ("COM1")
    private boolean connected;          //flag de conexão
    private SerialCache rxCache;        //cache de dados
    private boolean VirtualSerialPort;  //Indica se a porta utilizada é virtual (USB)
    static Logger log = Logger.getLogger(ExecuteSerialComm.class);

    /**
     * Construtor da classe <b>ComunicacaoSerial</b>. Recebe por parâmetro a
     * porta que deverá hospedar a conexão, a velocidade de comunicação e o
     * timeout de comunicação.
     *
     * @param String pPorta : Porta serial que hospedará a comunicação
     * @param int pBaudRate : Velocidade de comunicação
     * @since 1.0.0
     */
    public ExecuteSerialComm(String pPorta, int pBaudRate,
            boolean virtualSerialPort) {
        this.strPorts = pPorta;
        this.baudrate = pBaudRate;
        this.VirtualSerialPort = virtualSerialPort;
    }

    /**
     * Função responsável por setar os parâmetros de comunicação com o
     * equipamento. Retornará false caso não consiga setar os parâmetros.
     *
     * @param int pDataBits : Tamanho dos pacotes de dados
     * @param int pStopBits : Seta os bits de parada
     * @param int pParity : Paridade da comunicação
     * @return boolean
     * @since 1.0.0
     */
    public boolean setParametersCommunication(int pDataBits, int pStopBits,
            int pParity) {
        try {
            //configurando parâmetros de comunicação
            port.setSerialPortParams(
                    this.baudrate,
                    pDataBits,
                    pStopBits,
                    pParity);
            port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
            return true;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return false;
        }
    }

    /**
     * Obtém o id da porta serial definida no construtor da classe. O ID é
     * utilizado para realizar a comunicação com o equipamento.
     *
     * @return boolean
     * @see ComunicacaoSerial#strPorta
     * @since 1.0.0
     */
    public boolean getPortId() {
        Boolean IDPortaOk = false;
        try {
            //Verificando porta escolhida
            cp = CommPortIdentifier.getPortIdentifier(strPorts);
            if (cp == null) {
                IDPortaOk = false;
            }
            IDPortaOk = true;
        } catch (Exception e) {
            IDPortaOk = false;
        }
        return IDPortaOk;
    }

    /**
     * Abre a porta para início da comunicação Serial. As configurações de
     * conexão devem estar setadas.
     * <br>
     * <br>
     * Retorna false se não conseguir abrir a porta de comunicação Serial.
     *
     * @param int pTimeout : Timeout para tentar abrir a porta de comunicação
     * @return boolean
     * @see ComunicacaoSerial#SetaParametrosComunicacao
     * @since 1.0.0
     */
    public boolean openPort(int pTimeout) {
        try {
            if (getPortId()) {
                port = (SerialPort) cp.open("ComunicacaoSerial", pTimeout);
                port.addEventListener(this);
                port.notifyOnDataAvailable(true);
                connected = true;
                rxCache = new SerialCache();
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Fecha a comunicação com a porta serial setada. Retorna o resultado da
     * operação
     *
     * @return boolean
     * @see ComunicacaoSerial#abrePorta
     */
    public boolean closeCom() {
        try {
            port.close();
            connected = false;
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Retorna se a socket serial está conectada ou desconectada.
     *
     * @return boolean : conectado ou desconectado.
     */
    public boolean connected() {
        try {
            return connected;
        } catch (Exception e) {
            System.out.println(e);
            return false;
        }
    }

    /**
     * Retorna a porta que está sendo utilizada na instância da classe.
     *
     * @return strPorta String com a porta setada no construtor
     * @since 1.0.0
     */
    public String getPorts() {
        return strPorts;
    }

    /**
     * Retorna a velocidade utilizada atualmente na conexão.
     *
     * @return bautrate velocidade de comunicação setada no construtor
     */
    public int getBaudrate() {
        return baudrate;
    }

    /**
     * Envia um char array para o equipamento. As configurações da porta devem
     * estar previamente definidas.
     *
     * @param char[] txBuffer : Array com os dados em hexadecimal.
     * @return boolean True para execução correta, false para erro.
     * @see ComunicacaoSerial#abrePorta
     * @see ComunicacaoSerial#recebeResposta
     * @since 1.0.0
     */
    public boolean sendDatas(char[] txBuffer) {
        Boolean result = false;
        if (read == true) {
            try {
                //Pegando configurações para envio
                input = port.getOutputStream();
                //Enviando o buffer para a porta pré-definida 
                //Pegando o valor dos dados
                String aux = String.valueOf(txBuffer);
                //Escrevendo os bytes na porta Serial
                input.write(aux.getBytes("ISO-8859-1"));
                Thread.sleep(10);
                if (!VirtualSerialPort) //na VSP há erro ao usar o flush
                {
                    input.flush(); //Realizando o envio.
                }
                result = true;
            } catch (Exception e) {
                System.out.print(e);
                result = false;
            }
        }
        return result; //retornando valor
    }

    /**
     * Envia um char array para o equipamento. As configurações da porta devem
     * estar previamente definidas.
     *
     * @param char[] txBuffer : Array com os dados em hexadecimal.
     * @return boolean True para execução correta, false para erro.
     * @see ComunicacaoSerial#abrePorta
     * @see ComunicacaoSerial#recebeResposta
     * @since 1.0.0
     */
    public boolean sendDatas(String txBuffer) {
        Boolean result = false;
        if (read == true) {
            try {
                //Pegando configurações para envio
                input = port.getOutputStream();
                //Escrevendo os bytes na porta Serial
                input.write(txBuffer.getBytes("ISO-8859-1"));
                Thread.sleep(10);
                if (!VirtualSerialPort) //na VSP há erro ao usar o flush
                {
                    input.flush(); //Realizando o envio.
                }
                result = true;
            } catch (Exception e) {
                System.out.print(e);
                result = false;
            }
        }
        return result; //retornando valor
    }

    /**
     * Envia um byte para a placa de comunicação.
     *
     * @param chr
     * @return boolean True para execução correta, false para erro.
     * @since 1.0.0
     */
    public boolean sendChar(char chr) {
        Boolean result = false;
        char[] arr = new char[1];
        arr[0] = chr;
        if (read == true) {
            try {
                //Pegando configurações para envio
                input = port.getOutputStream();
                //Enviando o buffer para a porta pré-definida 
                //Pegando o valor dos dados
                String aux = String.valueOf(arr);
                //Escrevendo os bytes na porta Serial
                input.write(aux.getBytes("ISO-8859-1"));
                Thread.sleep(10);
                input.flush(); //Realizando o envio.
                result = true;
            } catch (Exception e) {
                result = false;
            }
        }
        return result; //retornando valor
    }

    /**
     * Retorna quantidade de dados para receber.
     *
     * @return int com a quantidade de dados
     */
    public int nrReceiveDatas() {
        int result = 0;
        try {
            output = port.getInputStream();
            result = output.available();
            result = rxCache.getCacheLength();
        } catch (Exception ex) {
            System.out.println(ex);

        }
        return result;
    }

    /**
     * Evento de recepção de dados.
     *
     * @param event
     */
    public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()) {
            case SerialPortEvent.BI:
            case SerialPortEvent.OE:
            case SerialPortEvent.FE:
            case SerialPortEvent.PE:
            case SerialPortEvent.CD:
            case SerialPortEvent.CTS:
            case SerialPortEvent.DSR:
            case SerialPortEvent.RI:
            case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
                break;
            case SerialPortEvent.DATA_AVAILABLE: {
                try {
                    //recebendo dados
                    output = port.getInputStream();
                    while (output.available() > 0) {
                        byte[] readBuffer = new byte[output.available()];
                        int numBytes = output.read(readBuffer);
                        if (numBytes > 0) {
                            //adicionando na cache                            
                            char[] aux = getChars(readBuffer);
                            rxCache.addDataCache(aux);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            break;
        }
    }

    /**
     * Recebe os dados da cache interna.
     *
     * @param data Vector que irá receber um char[] com os dados.
     * @return boolean com o resultado da operação
     * @since 1.0.0
     */
    public char[] receiveDatas() {
        try {
            if (write) {
                if (rxCache.getCacheLength() > 0) {
                    return rxCache.getDataCache();
                }
            }
        } catch (Exception e) {
            System.out.println("Erro durante recepção de dados : "
                    + e.getMessage());
        }
        return null;
    }

    /**
     * Recebe os dados da cache interna.
     *
     * @param data Vector que irá receber um char[] com os dados.
     * @return boolean com o resultado da operação
     * @since 1.0.0
     */
    public char[] receiveDatas(int timeout) {
        try {
            if (write) {
                int count = 0;
                do {
                    if (rxCache.getCacheLength() > 0) {
                        return rxCache.getDataCache();
                    }
                    count += 50;
                    Thread.sleep(50);
                } while (count < timeout);
            }
        } catch (Exception e) {
            System.out.println("Erro durante recepção de dados : "
                    + e.getMessage());
        }
        return null;
    }

    //Habilitando escrita. Somente uma operação é suportada por vez.
    public void enableWrite() {
        read = true;
        write = false;
    }
    //Habilitando leitura

    public void enableRead() {
        read = false;
        write = true;
    }

    public static char[] getChars(byte[] bytes) {
        Charset cs = Charset.forName("ISO-8859-1");
        ByteBuffer bb = ByteBuffer.allocate(bytes.length);
        bb.put(bytes);
        bb.flip();
        CharBuffer cb = cs.decode(bb);
        return cb.array();
    }

    public static String charToString(char[] buf) {
        return String.valueOf(buf);
    }
}
package comunication.serial;

import gnu.io.CommPortIdentifier;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * Lista as portas do usuário.
 *
 */
public class PortLists {

    protected List<String> ports;
    protected Enumeration listPorts;

    public PortLists() {
        try {
            listPorts = CommPortIdentifier.getPortIdentifiers();
            if (listPorts != null) {
                this.portList();
            }
        } catch (Exception e) {
            System.out.println("Port list " + e);
        }
    }

    //Retorna as portas disponíveis
    public List<String> getPorts() {
        return ports;
    }

    //Listando as portas seriais existentes
    private void portList() {
        try {
            ports = new ArrayList<String>();
            while (listPorts.hasMoreElements()) {
                CommPortIdentifier ips
                        = (CommPortIdentifier) listPorts.nextElement();
                ports.add(ips.getName());
            }
        } catch (Exception e) {
            System.out.println("Port list " + e);
        }
    }

    //Verificando existência da porta
    public boolean existPort(String pCom) {
        String temp;
        boolean e = false;
        while (listPorts.hasMoreElements()) {
            CommPortIdentifier ips
                    = (CommPortIdentifier) listPorts.nextElement();
            temp = ips.getName();
            if (temp.equals(pCom) == true) {  //Verificando se existe
                e = true;
            }
        }
        return e;
    }
}
package comunication.serial;

/**
 * Classe responsável por armazenar e organizar o acesso ao char[] que armazena
 * a cache recebida da porta serial. Para realizar o acesso a classe utiliza um
 * método privado sincronizado, evitando assim algum tipo de
 * nullPointerException.
 *
 *
 * @see SerialCache#SerialCache()
 */
public class SerialCache {

    private char[] rxCache; //Objeto char[] que armazena os dados

    /**
     * Construtor da classe SerialCache. Ao instanciar array interno é
     * automaticamente instanciado.
     */
    protected SerialCache() {
        rxCache = new char[0];
    }

    /**
     * Executa o acesso ao char[]. Recebe por parâmetro o char[] data que será o
     * array que trará os dados no caso de entrada. No caso de saída, os dados
     * serão inseridos nesse array que dever vir no tamanho correto.
     *
     * @param data parâmetro de entrada ou saída de dados.
     * @param in indica se é entrada de dados se for True. False para saída.
     */
    private synchronized void acessCache(char[] data, boolean in) {
        if (in) {
            //obtendo e armazenando dados
            char[] cache = new char[data.length + rxCache.length];
            System.arraycopy(rxCache, 0, cache, 0, rxCache.length);
            System.arraycopy(data, 0, cache, rxCache.length, data.length);
            rxCache = cache;
        } else {
            //passando dados para o array de saída
            for (int i = 0; i < data.length; i++) {
                data[i] = rxCache[i];
            }
            //limpando o array.
            dumpCache();
        }
    }

    /**
     * Retorna os dados armazenados na classe.
     *
     * @return char[] com os dados armazenados.
     */
    protected char[] getDataCache() {
        //criando char[] temporário para obter dados
        char[] temp = new char[rxCache.length];
        acessCache(temp, false);
        return temp;
    }

    /**
     * Adiciona dados na classe. Os dados ficarão armazenados até que sejam
     * recuperados.
     *
     * @param data Esse char[] contém os dados que serão armazenados.
     */
    protected void addDataCache(char[] data) {
        acessCache(data, true);
    }

    /**
     * Obtém o tamanho da cache de dados.
     *
     * @return int com o tamanho da cache.
     */
    protected int getCacheLength() {
        return rxCache.length;
    }

    /**
     * Remove os itens da cache de dados.
     */
    protected void dumpCache() {
        rxCache = new char[0];
    }

}
package comunication.serial;

import comunication.Comm;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Realiza a conexão via serial aos equipamentos.
 *
 */
public class SerialComm extends Comm {

    public static final int CONNECT_TIMEOUT = 200;
    private boolean isConnected;
    //comunicação
    comunication.serial.ExecuteSerialComm communication;

    public SerialComm(String port) {
        communication
                = new comunication.serial.ExecuteSerialComm(port,
                        comunication.serial.ExecuteSerialComm.v115200, false);
        isConnected = false;
    }

    /**
     * Conecta a um equipamento.
     *
     * @return resultado da operação.
     */
    public boolean connect() {
        boolean result = false;
        if (communication.openPort(CONNECT_TIMEOUT)) {
            communication.setParametersCommunication(comunication.serial.ExecuteSerialComm.DATABITS_8,
                    comunication.serial.ExecuteSerialComm.STOPBITS_1,
                    comunication.serial.ExecuteSerialComm.PARITY_NONE);
            result = true;
        }
        isConnected = result;
        return result;
    }

    /**
     * Desconecta do equipamento.
     *
     * @return resultado da operação.
     */
    public boolean disconnect() {
        boolean result = false;
        if (communication.connected()) {
            if (communication.closeCom()) {
                result = true;
            }
        }
        return result;
    }

    /**
     * Envia os dados a um equipamento
     *
     * @param data dados a serem enviados.
     * @return resultado da operação.
     */
    public boolean sendData(char[] data) {
        boolean result = false;
        communication.enableWrite();
        if (communication.sendDatas(data)) {
            result = true;
            communication.enableRead();
        }
        return result;
    }

    public char[] receiveData(int size) {
        char aux[] = communication.receiveDatas();
        return aux;
    }

    /**
     * Dados retornados.
     *
     * @return tamanho dos dados retornados.
     */
    public int availableData() {
        int auxInt = communication.nrReceiveDatas();
        return auxInt;
    }

    public boolean isReachable(int timeout) {
        boolean result = false;
        try {
            long startLong = new Date().getTime();
            long currentLong = System.currentTimeMillis();

            do {
                if (communication.getPortId()) {
                    result = true;
                    break;
                }

                Thread.sleep(100);
            } while ((currentLong - startLong) < timeout);

        } catch (Exception e) {
            System.out.println(e);
        }
        return result;
    }

    /**
     * Carrega as portas disponíveis.
     *
     * @return Portas disponíveis.
     */
    public static List<String> getAvailablePorts() {
        List<String> list = new ArrayList<String>();
        try {
            PortLists listPorts = new PortLists();
            List<String> ports = listPorts.getPorts();
            for (String port : ports) {
                if (port != null) {
                    list.add(port);
                }
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        return list;
    }

    /**
     * Verifica o estado da conexão.
     *
     * @return Estado da conexão (conectado ou não conectado).
     */
    public boolean isConnected() {
        return this.isConnected;
    }
}

 

 

 

 

 

 

 

 

 

 

 

adicionado 0 minutos depois
package equipment.protocol;

import equipment.protocol.command.Command;
import error.ErrorCode;
import authenticate.AuthenticationUtils;

/**
 * Faz o tratamento das mensagens que são enviadas ao equipamento, toda mensagem
 * antes de ser enviada ao equipamento primeiro é carregada nessa classe
 *
 */
public class Header {

    //Constantes 
    /*------------------------------===-----------------------------------------
     *                      Pacotes de comunicação
     *------------------------------===---------------------------------------*/
    private static final char HEADER_START_BTYE = 0x02;
    private static final int HEADER_START_BTYE_SIZE = 1;
    private static final int CHECK_SUN = 1;
    private static final int MIN_STEPS = 2;
    private static final char HEADER_END_BTYE = 0x03;
    private static final int HEADER_END_BTYE_SIZE = 1;
    private static final char HEADER_MIN_SIZE = 5; //Tamanho mínimo de um pacote
    /*------------------------------===-----------------------------------------
     *                 Separadores de parâmetros / dados
     *------------------------------===---------------------------------------*/
    public static final char HEADER_SEP_1 = '+';
    public static final char HEADER_SEP_2 = ']';
    public static final char HEADER_SEP_3 = '[';
    public static final char HEADER_SEP_4 = '}';
    public static final char HEADER_SEP_5 = '{';
    /*------------------------------===-----------------------------------------
     *                 Status do equipamento
     *------------------------------===---------------------------------------*/
    public static final String BIOMETRICS_NUMBER = "D";
    public static final String USERS_NUMBER = "U";
    public static final String REGISTER_NUMBER = "R";
    public static final String PAPER_SENSOR_ACTIVATED = "PP";
    public static final String NO_PAPER = "SP";
    public static final String BLOCKED_EQUIP = "TP";
    public static final String MPR_ERROR = "MRPE";
    public static final String WITHOUT_EMPLOYER = "SEMP";
    public static final String TICKETS_NUMBER = "QP";
    public static final String PRINTER = "PRN";

    /*------------------------------===-----------------------------------------
     *            Separadores de configuração do equipamento
     *------------------------------===---------------------------------------*/
    /**
     * Exemplo setConfiguration(Header.IP + "000.000.000.000");
     */
    public static final String IP = "IP[";

    /**
     * Exemplo setConfiguration(Header.PORT + "3000");
     */
    public static final String PORT = "PORTA_TCP[";

    /**
     * Exemplo setConfiguration(Header.DHCP + Header.ENABLE);
     */
    public static final String DHCP = "DHCP";
    public static final String ENABLE = "[H]";
    public static final String DISABLE = "[D]";

    //public static final int HEADER_ERR_UNKNOWN_CMD 10 //Comando desconhecido
    /*

     */
    /**
     * Realiza a montagem do cabeçalho conforme comando informado. Carrega todos
     * os dados necessários: SB, MI, Command version, dados do comando, checksum
     * e endbyte. Para desmontar o cabeçalho utilize: {@link Header#loadObject}.
     *
     * @param aesKey
     * @param obj Comando que será transformado em string.
     * @return Array com os dados do objeto.
     */
    public static char[] loadHeader(Command obj, String aesKey) {
        try {
            String nrMsg = String.valueOf(obj.getMessageNumber());
            int dataSize = obj.getData().length; // Tamanho dos dados excedentes
            char[] msg_obj = obj.getData();
            int nrMsgSize = nrMsg.length(); // Tamanho do indice da mensagem
            int idx = 0;
            char chksum = 0;
            int msgmless;
            char result[] = new char[1024];
            String cmd_complement = "00";
            //int idxTmp = 0;

            String strCmd
                    = (obj.isSend()
                            ? obj.getCommandId().getCmdSndCode()
                            : obj.getCommandId().getCmdRcvCode());
            int strCmdSize = strCmd.length();

            StringBuilder aux = new StringBuilder();

            if (nrMsgSize < 2) {
                aux.append("0" + nrMsg);
            } else {
                aux.append(nrMsg);
            }

            aux.append(HEADER_SEP_1); //separador

            //Carregando código String do comando (Ex: RH, EH, RC)
            for (int i = 0; i < strCmdSize; i++) {
                aux.append(strCmd.charAt(i));
            }

            aux.append(HEADER_SEP_1); //separador

            //Carregando outra parte do comando.
            for (int i = 0; i < cmd_complement.length(); i++) {
                aux.append(cmd_complement.charAt(i));
            }

            /*
             //Carregando outra parte do comando.
             for (int i = 0; i < cmd_complement.length(); i++) {
             arraytmp[idx++] = cmd_complement.charAt(i);
             }
             */
            for (int i = 0; i < msg_obj.length; i++) {
                aux.append(msg_obj[i]);
            }

            System.out.println(aux.toString());
            int sizeMsg;
            System.out.println(aux.toString());
            String tmp = aux.toString();
            char array[] = tmp.toCharArray();

            if (!aesKey.equals("")) {
                /*
                 * Criptografando
                 */
                byte encodedArr[] = AuthenticationUtils.encodeAES(aesKey,
                        aux.toString());
                /*
                 * Armazenando tamanho da msg criptografada.
                 */
                sizeMsg = encodedArr.length;

                //passar para o char[] data
                for (int j = 0; j < sizeMsg; j++) {
                    result[j] = (char) (encodedArr[j] & 0x00FF);
                }
                /*
                 *Limpando StringBuilder
                 */
                aux.setLength(0);
                /*
                 * Repassando mensagem criptografada, para um StringBuilder.
                 */
                for (int j = 0; j < sizeMsg; j++) {
                    aux.append(result[j]);
                }
                /*
                 * Caso não exista chave.
                 */
            } else {
                //calculando o tamanho da primeira parte montada da mensagem
                sizeMsg = aux.toString().length();
            }

            //Carregando tamanho necessário para o pacote de dados (+1 é do chksum)
            // Esse 1 veio do HEADER_SEP_1 que possui tamanho 1
            int size = HEADER_START_BTYE_SIZE + MIN_STEPS + sizeMsg
                    + HEADER_END_BTYE_SIZE + CHECK_SUN;

            //Arraytmp é do tamanho da mensagem
            char[] arraytmp = new char[size]; //Criando array de dados

            arraytmp[idx++] = HEADER_START_BTYE;

            //Carregando tamanho do array no próprio array (para equip. saber)
            //idxTmp = idx;
            arraytmp[idx++] = (char) (size & 0xFF);
            msgmless = (int) arraytmp[idx - 1] - 5; // Desconta <SB><XXXX><II><CS><EB>
            arraytmp[idx - 1] = (char) msgmless;
            arraytmp[idx++] = (char) (size >> 8 & 0xFF);

            /*
             //Carregando número da mensagem
             for (int i = 0; i < nrMsgSize; i++) {
             arraytmp[idx++] = nrMsg.charAt(i);
             }

             arraytmp[idx++] = HEADER_SEP_1; //separador

             //Carregando código String do comando (Ex: RH, EH, RC)
             for (int i = 0; i < strCmdSize; i++) {
             arraytmp[idx++] = strCmd.charAt(i);
             }

             arraytmp[idx++] = HEADER_SEP_1; //separador
             */
            //verifica se o objeto possui parâmetros adicionais
            if (aux.length() > 0) {
                //Carregando dados do objeto no array
                for (int i = 0; i < aux.length(); i++) {
                    arraytmp[idx++] = aux.toString().toCharArray()[i];
                }
            }
            System.out.println(aux.length());
            int x = size - 2;
            System.out.println("size = " + x);
            for (int j = 1; j < size - 2; j++) { //calculando checksum dos dados
                chksum ^= arraytmp[j];
            }

            arraytmp[idx++] = chksum; //carregando checksum no array

            arraytmp[idx++] = HEADER_END_BTYE; //Endbyte

            System.out.println(arraytmp);
            return arraytmp;

        } catch (Exception e) {
            System.out.println(e);
        }
        return null;
    }

    /**
     * Desmonta, faz a validação e trata as mensagens recebidas pelo
     * equipamento.
     *
     * @param data Dados que devem ser tratados (resposta do equipamento).
     * @param cmd Objeto que deve ser desmontado para fazer validações na
     * mensagem recebida pelo equipamento.
     * @param aesKey Chave AES que deve ser usada (se necessário) para
     * descriptografar as mensagens (data) recebidas do equipamento.
     * @return Resultado da operação.
     */
    public static boolean loadObject(char[] data, Command cmd, String aesKey) {
        boolean result = true;
        try {
            int i = 0, j; //Índice auxiliar
            int size = data.length;
            char chksum = 0; // Calcular chksum
            if (size >= HEADER_MIN_SIZE) { //Verificando se possui tamanho mínimo
                int idx = 0; //Índice auxiliar
                if (data[idx++] == HEADER_START_BTYE) { //Conferindo Start byte
                    //Conferindo tamanho do pacote
                    int pcktSize = data[idx++];
                    pcktSize += data[idx++] << 8;

                    if (pcktSize == size - 5) {
                        size -= 2; //Descontando endByte e checksum

                        for (j = 1; j < size; j++) { //calculando checksum dos dados
                            chksum ^= data[j];
                        }

                        if (chksum == data[size]) { //FIXME Validar checksum antes de entrar
                            String msgIndex = ""; // Indice da Mensagem
                            String cmdCode = ""; // RH
                            String errorCode = ""; // Codigo de erro
                            // char cmdData[] = new char[size]; // 09/07/12 19:41:20]00/00/00]00/00/00
                            String cmdData = "";
                            // Verifica se a mensagem veio criptografada
                            if (!aesKey.equals("")) {
                                byte iv[] = new byte[16];
                                byte encodedArr[] = new byte[pcktSize - 16];
                                j = 0;

                                /* passa os primeiros 16 bytes para o iv
                                 * (bytearray).
                                 */
                                // Tente usar i < 16
                                for (i = 3; (i < 19) && (i < pcktSize); i++) {
                                    iv[j] = (byte) (data[i] & 0x00FF);
                                    j++;
                                }
                                j = 0;
                                /*
                                 * passa o restante para o encodedArr
                                 */
                                for (i = i; i < size; i++) {
                                    encodedArr[j] = (byte) (data[i] & 0x00FF);
                                    j++;
                                }
                                //descriptografa a mensagem recebida
                                byte decodedArr[] = AuthenticationUtils.decodeAES(
                                        aesKey, encodedArr, iv);
                                // tamanho do decodedArr
                                size = decodedArr.length;
                                //ajusta tamanho do char[] data 
                                data = new char[decodedArr.length];
                                //passa de Byte para char[] 
                                for (j = 0; j < size; j++) {
                                    data[j] = (char) (decodedArr[j] & 0x00FF);
                                }
                                idx = 0;
                            }

                            //Carregar indice da mensagem
                            while (data[idx] != HEADER_SEP_1) {
                                msgIndex += data[idx++];
                            }
                            idx++; // Necessário para pular o '+'

                            //Exemplo: 01+EH+00
                            //Carregando índice da mensagem
                            //TODO implementar
                            //Carregando código do comando
                            while ((idx < size) && (data[idx] != HEADER_SEP_1)) {
                                cmdCode += String.valueOf(data[idx++]);
                            }

                            idx++; // pular o + para chegar no errorCode

                            // Verifica errorCode
                            while ((idx < size) && (data[idx] != HEADER_SEP_1)) {
                                if (data[idx] != '

Você pode extrair vários trechos de código e montar o seu a partir deste meu ! Basta estudar o código, entender um pouco do fluxo etc ...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×