001package com.pi4j.io.serial;
002
003/*
004 * #%L
005 * **********************************************************************
006 * ORGANIZATION  :  Pi4J
007 * PROJECT       :  Pi4J :: Java Library (Core)
008 * FILENAME      :  SerialDataEvent.java
009 *
010 * This file is part of the Pi4J project. More information about
011 * this project can be found here:  https://www.pi4j.com/
012 * **********************************************************************
013 * %%
014 * Copyright (C) 2012 - 2019 Pi4J
015 * %%
016 * This program is free software: you can redistribute it and/or modify
017 * it under the terms of the GNU Lesser General Public License as
018 * published by the Free Software Foundation, either version 3 of the
019 * License, or (at your option) any later version.
020 *
021 * This program is distributed in the hope that it will be useful,
022 * but WITHOUT ANY WARRANTY; without even the implied warranty of
023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
024 * GNU General Lesser Public License for more details.
025 *
026 * You should have received a copy of the GNU General Lesser Public
027 * License along with this program.  If not, see
028 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
029 * #L%
030 */
031
032
033import java.io.IOException;
034import java.nio.ByteBuffer;
035import java.nio.CharBuffer;
036import java.nio.charset.Charset;
037import java.nio.charset.StandardCharsets;
038import java.util.EventObject;
039
040/**
041 * <p> This class provides the serial data event object.</p>
042 *
043 * <p>
044 * Before using the Pi4J library, you need to ensure that the Java VM in configured with access to
045 * the following system libraries:
046 * <ul>
047 * <li>pi4j</li>
048 * <li>wiringPi</li>
049 * </ul>
050 * <blockquote> This library depends on the wiringPi native system library.</br> (developed by
051 * Gordon Henderson @ <a href="http://wiringpi.com/">http://wiringpi.com/</a>)
052 * </blockquote>
053 * </p>
054 *
055 * @see com.pi4j.io.serial.Serial
056 * @see SerialDataEventListener
057 * @see com.pi4j.io.serial.SerialDataReader
058 * @see com.pi4j.io.serial.SerialFactory
059 *
060 * @see <a href="https://www.pi4j.com/">https://www.pi4j.com/</a>
061 * @author Robert Savage (<a
062 *         href="http://www.savagehomeautomation.com">http://www.savagehomeautomation.com</a>)
063 */
064public class SerialDataEvent extends EventObject {
065
066    private static final long serialVersionUID = 1L;
067    private final Serial serial;
068    private byte[] cachedData = null;
069
070    /**
071     * Default event constructor.
072     */
073    public SerialDataEvent(Serial serial) {
074        super(serial);
075        this.serial = serial;
076    }
077
078    /**
079     * Default event constructor.
080     */
081    public SerialDataEvent(Serial serial, byte[] data) {
082        this(serial);
083        this.cachedData = data;
084    }
085
086    /**
087     * Get the serial interface instance
088     *
089     * @return serial interface
090     */
091    public Serial getSerial(){
092        return this.serial;
093    }
094
095    /**
096     * Get an instance of the serial data reader
097     *
098     * @return serial data reader interface
099     */
100    public SerialDataReader getReader(){
101        return this.serial;
102    }
103
104    /**
105     * Get the number of bytes available in the serial data
106     *
107     * @return number of bytes available
108     * @throws IOException
109     */
110    public int length() throws IOException {
111        if(cachedData != null){
112            return cachedData.length;
113        }
114        return getReader().available();
115    }
116
117    /**
118     * Get all the bytes (byte-array) available in the serial data receive buffer
119     *
120     * @return byte array containing all bytes available in serial data receive buffer
121     * @throws IOException
122     */
123    public byte[] getBytes() throws IOException {
124        if(cachedData == null){
125            if(getReader().available() > 0) {
126                cachedData = getReader().read();
127            }
128            else{
129                cachedData = new byte[0];
130            }
131        }
132        return cachedData;
133    }
134
135    /**
136     * Get all the bytes (byte-buffer) available in the serial data receive buffer
137     *
138     * @return ByteBuffer containing all bytes available in serial data receive buffer
139     * @throws IOException
140     */
141    public ByteBuffer getByteBuffer() throws IOException {
142        return ByteBuffer.wrap(getBytes());
143    }
144
145    /**
146     * Get a string representation of the bytes available in the serial data receive buffer
147     *
148     * @param charset the character-set used to construct the string from the underlying byte array
149     * @return string of data from serial data receive buffer
150     * @throws IOException
151     */
152    public String getString(Charset charset) throws IOException {
153        return getCharBuffer(charset).toString();
154    }
155
156    /**
157     * Get an ASCII string representation of the bytes available in the serial data receive buffer
158     *
159     * @return ASCII string of data from serial data receive buffer
160     * @throws IOException
161     */
162    public String getAsciiString() throws IOException {
163        return getCharBuffer(StandardCharsets.US_ASCII).toString();
164    }
165
166    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
167
168    /**
169     * Get a HEX string representation of the bytes available in the serial data receive buffer
170     *
171     * @return HEX string of comma separated data bytes from serial data receive buffer
172     * @throws IOException
173     */
174    public String getHexByteString() throws IOException {
175        return getHexByteString(null, ",", null);
176    }
177
178    /**
179     * Get a HEX string representation of the bytes available in the serial data receive buffer
180     *
181     * @param prefix optional prefix string to append before each data byte
182     * @param separator  optional separator string to append in between each data byte sequence
183     * @param suffix optional suffix string to append after each data byte
184     * @return HEX string of data bytes from serial data receive buffer
185     * @throws IOException
186     */
187    public String getHexByteString(CharSequence prefix, CharSequence separator, CharSequence suffix) throws IOException {
188        byte data[] = getBytes();
189        StringBuilder sb = new StringBuilder();
190        for (int i = 0; i < data.length; i++)
191        {
192            if(i > 0) sb.append(separator);
193            int v = data[i] & 0xff;
194            if(prefix != null) sb.append(prefix);
195            sb.append(hexArray[v >> 4]);
196            sb.append(hexArray[v & 0xf]);
197            if(suffix != null) sb.append(suffix);
198        }
199        return sb.toString();
200    }
201
202    /**
203     * Get a character buffer of the bytes available in the serial data receive buffer
204     *
205     * @param charset the character-set used to construct the character buffer from the underlying byte array
206     * @return CharBuffer of data from serial data receive buffer
207     * @throws IOException
208     */
209    public CharBuffer getCharBuffer(Charset charset) throws IOException {
210        return charset.decode(getByteBuffer());
211    }
212
213    /**
214     * <p>discard/drain all available bytes from the serial data receive buffer</p>
215     */
216    public void discardData() throws IllegalStateException, IOException{
217        getReader().discardData();
218    }
219
220}