/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package robotinterface.robot.connection; import gnu.io.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import java.awt.EventQueue; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import robotinterface.drawable.util.QuickFrame; import robotinterface.gui.panels.SimulationPanel; import robotinterface.util.observable.Observer; import robotinterface.robot.Robot; import static robotinterface.robot.connection.Serial.charset; import static robotinterface.robot.connection.Serial.printBytes; import robotinterface.robot.device.Compass; import robotinterface.robot.device.HBridge; import robotinterface.robot.device.IRProximitySensor; import robotinterface.robot.device.ReflectanceSensorArray; import robotinterface.robot.simulation.VirtualConnection; import robotinterface.util.ByteCharset; /** * * @author antunes */ public class Serial implements Connection, SerialPortEventListener { private static boolean FAIL_LOAD_LIBRARY = false; private ArrayList<Observer<ByteBuffer, Connection>> observers; private SerialPort serialPort; private String defaultPort = null; private boolean isConnected = false; private boolean available = false; private int sendedPackages = 0; private int receivedPackages = 0; private static final String PORT_NAMES[] = { "/dev/tty.usbserial-A9007UX1", // Mac OS X "/dev/ttyUSB#", // Linux "/dev/ttyACM#", // Linux USB 3.0 "COM#", // Windows }; /** * A BufferedReader which will be fed by a InputStreamReader converting the * bytes into characters making the displayed results codepage independent */ private InputStream input; private BufferedReader bufferedReader; private ByteBuffer buffer; public static Charset charset = new ByteCharset(); /** * The output stream to the port */ private OutputStream output; /** * Default bits per second for COM port. */ private int dataRate = 9600; /** * Milliseconds to block while waiting for port open */ private static final int TIME_OUT = 2000; private static final int PORT_SEARCH = 10; public Serial(int dataRate) { observers = new ArrayList<>(); this.dataRate = dataRate; buffer = ByteBuffer.allocate(256); } public int getSendedPackages() { return sendedPackages; } public int getReceivedPackages() { return receivedPackages; } public String getDefaultPort() { return defaultPort; } public void setDefaultPort(String defaultPort) { this.defaultPort = defaultPort; } @Override public void send(final byte[] data) { /*byte length = (byte) data.length; byte[] newdata = new byte[length + 1]; System.arraycopy(data, 0, newdata, 1, length); newdata[0] = length;*/ try { sendedPackages++; output.write(data.length); output.write(data); // output.flush(); //trava a thread main! pq??? } catch (IOException ex) { System.out.println("Send fail!"); } } // public void send(final byte[] data, boolean sendLength) { // if (sendLength) { // byte length = (byte) data.length; // byte[] newdata = new byte[length + 1]; // System.arraycopy(data, 0, newdata, 1, length); // newdata[0] = length; // send(newdata); // } else { // send(data); // } // } @Override public void send(ByteBuffer data) { int length = data.remaining(); byte[] msg = new byte[length]; data.get(msg); send(msg); } @Override public boolean available() { return available; } @Override public int receive(byte[] b, int size) { available = false; if (available && buffer != null) { buffer.get(b); return buffer.position(); } else { return 0; } } public boolean tryConnect(String port) { CommPortIdentifier portId = null; Enumeration portEnum = null; try { portEnum = CommPortIdentifier.getPortIdentifiers(); } catch (Throwable t) { // t.printStackTrace(); throw new Error(); } if (portEnum == null) { return false; } //First, Find an instance of serial port as set in PORT_NAMES. while (portEnum.hasMoreElements()) { CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement(); if (currPortId.getName().equals(port)) { portId = currPortId; break; } } if (portId == null) { //Could not find COM port return false; } try { // open serial port, and use class name for the appName. serialPort = (SerialPort) portId.open(this.getClass().getName(), TIME_OUT); // set port parameters serialPort.setSerialPortParams(dataRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); //teste web: http://www.devmedia.com.br/utilizando-a-api-rxtx-para-manipulacao-da-serial-parte-iii/7171 serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); // open the streams input = serialPort.getInputStream(); bufferedReader = new BufferedReader(new InputStreamReader(input, charset)); input = serialPort.getInputStream(); output = serialPort.getOutputStream(); // add event listeners serialPort.addEventListener(this); serialPort.notifyOnDataAvailable(true); } catch (PortInUseException e) { //porta ocupada return false; } catch (Exception e) { return false; } return true; } public Collection<String> getAvailableDevices() { ArrayList<String> avaliableDevices = new ArrayList<>(); if (FAIL_LOAD_LIBRARY) { return avaliableDevices; } for (String name : PORT_NAMES) { if (name.contains("#")) { for (int i = 0; i < PORT_SEARCH; i++) { String device = name.replace("#", "" + i); //adiciona portas ocultas e bloqueadas (Linux) System.setProperty("gnu.io.rxtx.SerialPorts", device); try { if (tryConnect(device)) { avaliableDevices.add(device); closeConnection(); } } catch (Throwable t) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JOptionPane.showMessageDialog(null, "Falha ao carregar a biblioteca da porta serial.\nApenas simulação virtual disponivel.", "Erro", JOptionPane.ERROR_MESSAGE); } }); FAIL_LOAD_LIBRARY = true; return avaliableDevices; } } } } return avaliableDevices; } @Override public boolean establishConnection() { isConnected = false; // Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { // @Override // public void run() { // closeConnection(); // } // })); if (defaultPort == null) { for (String name : PORT_NAMES) { if (name.contains("#")) { for (int i = 0; i < PORT_SEARCH; i++) { String device = name.replace("#", "" + i); //adiciona portas ocultas e bloqueadas (Linux) System.setProperty("gnu.io.rxtx.SerialPorts", device); isConnected = tryConnect(device); if (isConnected) { System.out.println(device); try { Thread.sleep(1000); //espera 1s para a conexão funcionar } catch (InterruptedException ex) { } return true; } } } } } else { //adiciona portas ocultas e bloqueadas (Linux) System.setProperty("gnu.io.rxtx.SerialPorts", defaultPort); isConnected = tryConnect(defaultPort); if (isConnected) { try { Thread.sleep(1000); //espera 1s para a conexão funcionar } catch (InterruptedException ex) { } return true; } } return false; } @Override public void closeConnection() { if (serialPort != null) { serialPort.removeEventListener(); serialPort.close(); } } @Override public boolean isConnected() { return isConnected; } @Override public void attach(Observer<ByteBuffer, Connection> observer) { observers.add(observer); } @Override public void detach(Observer<ByteBuffer, Connection> observer) { observers.remove(observer); } boolean newMessage = false; @Override synchronized public void serialEvent(SerialPortEvent spe) { if (spe.getEventType() == SerialPortEvent.DATA_AVAILABLE) { try { //define a posição como o inicio do buffer e remove a marca e o limite buffer.clear(); // System.out.println("start"); byte[] tmpByte = new byte[1]; //preenche o buffer while (true) { //System.out.println("\t1: " + System.currentTimeMillis()); //obtem uma string delimitada por '\n', '\t' ou "\t\n" String str = bufferedReader.readLine(); // printBytes(str); //obtem os bytes codificados na string com o Charset personalizado byte[] data = str.getBytes(charset); if (data.length > 1) { buffer.put(data, 1, data.length - 1); //System.out.println("\t2: " + System.currentTimeMillis()); //printBytes(data, data.length); receivedPackages++; available = true; } if (bufferedReader.ready()) { // while (input.available() > 0) { // input.read(tmpByte); // buffer.put(tmpByte[0]); // } break; //não remove os valores 10 presentes no meio da mensagem //buffer.put((byte) '\n'); } else { break; } } // printBytes(buffer.array(), buffer.array().length); byte[] w = buffer.array(); for (int i = 0; i < w.length; i++) { if (w[i] == '\n') { System.err.println("FUNCIONOU!!"); System.exit(0); } } // byte [] size = new byte[1]; // input.read(size); // // byte [] data = new byte[size[0]]; // // for (int i = 0; i < size[0]; i++){ // // } // //sem usar string // while (true) { // //obtem uma string delimitada por '\n', '\t' ou "\t\n" // int size = input.read(); // System.out.println("size: "+ size); // byte [] data = new byte[size]; //// String str = bufferedReader.readLine(); //// printBytes(str); // r++; // System.out.println("S:" + s + " x R:" + r); // //obtem os bytes codificados na string com o Charset personalizado // buffer.put(data);//str.getBytes(charset)); // if (bufferedReader.ready()) { // //não remove os valores 10 presentes no meio da mensagem // buffer.put((byte) '\n'); // } else { // break; // } // } //define esta posição como limite e retorna para a posição 0 //buffer.limit() retorna o tamanho da mensagem buffer.flip(); /* * Exemplo de como usar um ByteBuffer para leitura * ByteBuffer cpy = buffer.asReadOnlyBuffer(); System.out.println("Tamanho:" + cpy.limit()); int k = 0; //contador while (cpy.remaining() > 0){ System.out.println(k + " : " + (byte)cpy.get()); k++; } */ //se for possivel ler um ou mais bytes if (buffer.remaining() > 0 && !observers.isEmpty()) { //notify observers for (Observer<ByteBuffer, Connection> o : observers) { o.update(buffer.asReadOnlyBuffer(), this); } available = false; } //System.out.println("\t3: " + System.currentTimeMillis()); } catch (Exception e) { e.printStackTrace(); System.err.println(e.toString()); } } } public static void printBytes(String str) { byte[] array = str.getBytes(charset); printBytes(array, array.length); } public static void printBytes(byte[] array, int size) { System.out.print("Received: "); System.out.print("[" + size + "]{"); for (int i = 0; i < size; i++) { System.out.print("," + array[i]); } System.out.println("}"); } public static void main(String[] args) { Serial s; s = new Serial(57600); //s = new VirtualConnection(s); // s = new VirtualConnection(); /*Robot r = new Robot(); r.add(new HBridge()); r.add(new Compass()); r.add(new IRProximitySensor()); r.add(new ReflectanceSensorArray()); s.attach(r); if (s instanceof VirtualConnection) { VirtualConnection v = (VirtualConnection) s; v.setRobot(r); }*/ ArrayList<byte[]> testMessages = new ArrayList<>(); /* PRIMEIROS TESTES */ // testMessages.add(new byte[]{2, 11, 3, 9, 'a', 'n', 'd', 'e', 'r', 's', 'o', 'n', '\n'}); // // testMessages.add(new byte[]{3, 0, 10, 'a', 'n', 'd', 'e', 'r', 's', 'o', 'n', '2', '\n'}); // testMessages.add(new byte[]{4, 0, 0});//get clock // testMessages.add(new byte[]{4, 1, 0});//get hbridge // testMessages.add(new byte[]{4, 2, 0});//get compass // testMessages.add(new byte[]{4, (byte) 223, 0});//get freeRam // testMessages.add(new byte[]{5, 1, 2, 0, 90, 5, 1, 2, 1, -90}); //rotaciona // testMessages.add(new byte[]{5, 1, 2, 0, (byte) 0, 5, 1, 2, 1, (byte) 0}); //para // testMessages.add(new byte[]{5, 1, 2, 0, -90, 5, 1, 2, 1, 90}); //rotaciona // testMessages.add(new byte[]{5, 1, 2, 0, (byte) 0, 5, 1, 2, 1, (byte) 0}); //para /* ROBO GENERICO */ // testMessages.add(new byte[]{4, (byte) 223, 0});//get freeRam // for (byte b = 0; b < 5; b++) { //adiciona 5 leds nos pinos 9->13 // testMessages.add(new byte[]{6, 1, 1, (byte) (b + 9)}); //o array de led começa no pino 9 // testMessages.add(new byte[]{4, (byte) 223, 0});//get freeRam // for (int i = 0; i < 2; i++) { // testMessages.add(new byte[]{4, (byte) (b + 1), 0}); //get status LED b+1 (0 = clock) // testMessages.add(new byte[]{5, (byte) (b + 1), 1, (byte) 255}); //set LED b+1 ON // testMessages.add(new byte[]{4, (byte) (b + 1), 0}); //get status LED b+1 (0 = clock) // testMessages.add(new byte[]{5, (byte) (b + 1), 1, 0}); //set LED b+1 OFF // } // } // testMessages.add(new byte[]{4, (byte) 223, 0});//get freeRam /* * Resultados (bytes): * Arduino MEGA (8k): * FreeRam: 6977 - apenas arduino+lib+serial * FreeRam: 6954 - +1 led * FreeRam: 6929 - +1 led * Arduino 2009 (2k): * FreeRam: 1299 - apenas arduino+lib+serial * FreeRam: 1272 - +1 led * FreeRam: 1243 - +1 led */ /* NOVAS FUNÇÕES DE GIRAR */ // ByteBuffer bf = ByteBuffer.allocate(8); // bf.putChar((char) 180); // byte[] tmp = new byte[2]; // bf.flip(); // bf.order(ByteOrder.LITTLE_ENDIAN); // bf.get(tmp); // // testMessages.add(new byte[]{4, 0, 0});//get clock // // testMessages.add(new byte[]{9, 0, 2, 1, 2, 3, tmp[1], tmp[0], 10}); /* RESETA AS FUNÇÕES E PONTE H */ // testMessages.add(new byte[]{7, (byte) 222});//reset all /* RESETA O SISTEMA (funcionando) */ // testMessages.add(new byte[]{7, (byte) 224});//reset system // testMessages.add(new byte[]{4, (byte) 223, 0});//get freeRam // testMessages.add(new byte[]{6, 5, 1, 17});//add dist // testMessages.add(new byte[]{4, (byte) 223, 0});//get freeRam // testMessages.add(new byte[]{7, (byte) 224});//reset system // testMessages.add(new byte[]{4, (byte) 223, 0});//get freeRam // testMessages.add(new byte[]{6, 5, 1, 17});//add dist // testMessages.add(new byte[]{4, (byte) 223, 0});//get freeRam /* MAPA DE PONTOS PELO SENSOR DE DISTÂNCIA - bug threads */ /*testMessages.add(new byte[]{7, (byte) 224});//reset system testMessages.add(new byte[]{6, 5, 1, 17});//add dist // testMessages.add(new byte[]{6, 4, 6, 0, 3, 4, 16, (byte) 200, 0});//add reflet testMessages.add(new byte[]{5, 1, 2, 0, 30, 5, 1, 2, 1, -30}); //rotaciona for (int i = 0; i < 5000; i++) { // testMessages.add(new byte[]{4, 2, 0, 4, 3, 0, 4, 4, 1, 0});//get compass & get dist & get reflet testMessages.add(new byte[]{Robot.CMD_GET, Robot.XTRA_ALL, 0});//get all } SimulationPanel p = new SimulationPanel(); p.addRobot(r); r.setEnvironment(p.getEnv()); QuickFrame.create(p, "Teste Simulação").addComponentListener(p); */ /* TESTE DO RÁDIO */ //quando uma mensagem chega é exibido "S:10 x R:10" //ou seja 10 mensagens enviadas e 10 recebidas //ATENÇÃO: trocar intervalo de tempo na linha ~389 //coloca 100 mensagens na lista de espera int test = 100; for (int i = 0; i < test; i++) { testMessages.add(new byte[]{1, 2, 3, 4, 5});//get clock }// // testMessages.add(new byte[]{2, });//get clock //// testMessages.add(new byte[]{3, 4, (byte) 223, 0});//get freeRam // } if (s.establishConnection()) { System.out.println("connected"); long timeSum = 0; byte[] buffer = new byte[20]; for (int i = 0; i < 1; i++) { //repetição int send = 0; for (byte[] message : testMessages) { send++; boolean timeout = false; long mtimestamp = System.currentTimeMillis(); int w = ((Serial) s).getReceivedPackages(); s.send(message); try { loop: while (!((Serial) s).available()) {//w == ((Serial)s).getReceivedPackages()/*((Serial) s).receivedPackages*/) { //tempo maximo para enviar: ~20ms da RXTXcomm + 8ms do radio Thread.sleep(1); //tempo maximo para enviar: ~20ms da RXTXcomm + 8ms do radio //w++; if (System.currentTimeMillis() - mtimestamp > 1000) { // s.send(message); //w = 0; timeout = true; test--; System.out.println("Timeout"); break loop; } // } catch (InterruptedException ex) { // Logger.getLogger(Serial.class.getName()).log(Level.SEVERE, null, ex); } } catch (InterruptedException ex) { } if (!timeout) { s.receive(buffer, buffer.length); long rtt = System.currentTimeMillis() - mtimestamp; timeSum += rtt; System.out.println(" @Time: " + rtt + "ms"); } try { Thread.sleep(10); } catch (InterruptedException ex) { } // } // System.out.print("Sended: "); // System.out.print(send + "\t- [" + message.length + "]{"); // for (byte b : message) { // System.out.print("," + b); // } // System.out.print("}"); } System.out.println("\nAverage Time: " + (timeSum / test) + "ms"); try { Thread.sleep(1000); } catch (InterruptedException ex) { } } } else { System.out.println("fail"); } System.out.println("Fim"); System.exit(0); } }