Java tutorial
/** * Copyright (C) 2011-2013 Michael Vogt <michu@neophob.com> * * This file is part of PixelController. * * PixelController is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PixelController is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PixelController. If not, see <http://www.gnu.org/licenses/>. */ package com.neophob.sematrix.core.output.tpm2; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.Adler32; import org.apache.commons.lang3.StringUtils; import com.neophob.sematrix.core.output.NoSerialPortFoundException; import com.neophob.sematrix.core.output.OutputHelper; import com.neophob.sematrix.core.output.Serial; import com.neophob.sematrix.core.properties.ColorFormat; /** * library to communicate with an TPM2 serial device using the tpm2net protocol * created for ledstyles.de * * @author Michael Vogt / neophob.com * */ public class Tpm2Serial { /** The log. */ private static final Logger LOG = Logger.getLogger(Tpm2Serial.class.getName()); /** internal lib version. */ public static final String VERSION = "1.1"; private static Adler32 adler = new Adler32(); /** The baud. */ private int baud; /** The port. */ private Serial port; /** map to store checksum of image. */ private long lastDataMap; /** * Create a new instance to communicate with the tpm2 device. * * @param app the app * @throws NoSerialPortFoundException the no serial port found exception */ public Tpm2Serial(int baud) throws NoSerialPortFoundException { this(null, baud); } /** * Create a new instance to communicate with the rainbowduino. * * @param app the app * @param portName the port name * @throws NoSerialPortFoundException the no serial port found exception */ public Tpm2Serial(String portName, int baud) throws IllegalArgumentException, NoSerialPortFoundException { LOG.log(Level.INFO, "Initialize Tpm2Serial lib v{0}", VERSION); this.baud = baud; lastDataMap = 0L; String serialPortName = ""; if (StringUtils.isNotBlank(portName)) { //open specific port LOG.log(Level.INFO, "Open specific port: {0}", portName); serialPortName = portName; openPort(portName); } else { //try to find the port String[] ports = Serial.list(); for (int i = 0; port == null && i < ports.length; i++) { LOG.log(Level.INFO, "Open port: {0}", ports[i]); try { serialPortName = ports[i]; openPort(ports[i]); //catch all, there are multiple exception to catch (NoSerialPortFoundException, PortInUseException...) } catch (Exception e) { // search next port... } } } if (port == null) { throw new NoSerialPortFoundException("Error: no serial port found!"); } LOG.log(Level.INFO, "found serial port: " + serialPortName); } /** * clean up library. */ public void dispose() { if (connected()) { port.stop(); } } /** * return the version of the library. * * @return String version number */ public String version() { return VERSION; } /** * * @return */ public String getConnectedPort() { if (!connected()) { return null; } return port.port.getName(); } /** * return connection state of lib. * * @return wheter rainbowudino is connected */ public boolean connected() { return (port != null); } /** * Open serial port with given name. Send ping to check if port is working. * If not port is closed and set back to null * * @param portName the port name * @throws NoSerialPortFoundException the no serial port found exception */ private void openPort(String portName) throws NoSerialPortFoundException { try { port = new Serial(portName, this.baud); port.output.write("PXL".getBytes()); } catch (Exception e) { LOG.log(Level.WARNING, "Failed to open port <" + portName + ">", e); if (port != null) { port.stop(); } port = null; throw new NoSerialPortFoundException("Failed to open port " + portName + ": " + e); } } /** * wrapper class to send a RGB image to the miniDmx device. * the rgb image gets converted to the miniDmx compatible * "image format" * * @param data rgb data (int[64], each int contains one RGB pixel) * @param colorFormat the color format * @return true if send was successful */ public boolean sendRgbFrame(int[] data, ColorFormat colorFormat) { return sendFrame(OutputHelper.convertBufferTo24bit(data, colorFormat)); } /** * get md5 hash out of an image. used to check if the image changed * * @param data the data * @return true if send was successful */ private boolean didFrameChange(byte data[]) { adler.reset(); adler.update(data); long l = adler.getValue(); if (lastDataMap == l) { //last frame was equal current frame, do not send it! return false; } //update new hash lastDataMap = l; return true; } /** * @param data byte[3*8*4] * @return true if send was successful * @throws IllegalArgumentException the illegal argument exception */ public boolean sendFrame(byte data[]) throws IllegalArgumentException { if (didFrameChange(data)) { writeSerialData(data); } return false; } public Serial getPort() { return port; } /** * send the data to the serial port. * * @param cmdfull the cmdfull * */ private synchronized void writeSerialData(byte[] cmdfull) { if (port == null) { LOG.log(Level.INFO, "port not ready (null)!"); return; } try { port.output.write(cmdfull); //port.output.flush(); //DO NOT flush the buffer... hmm not sure about this, processing flush also //and i discovered strange "hangs"... } catch (Exception e) { LOG.log(Level.WARNING, "Error sending serial data!", e); } } }