View Javadoc
1   package fr.ifremer.tutti.ichtyometer.feed;
2   
3   /*
4    * #%L
5    * Tutti :: Ichtyometer API
6    * %%
7    * Copyright (C) 2012 - 2014 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.base.Preconditions;
26  import com.google.common.io.Closeables;
27  import fr.ifremer.tutti.ichtyometer.IchtyometerClient;
28  import fr.ifremer.tutti.ichtyometer.feed.event.IchtyometerFeedReaderEvent;
29  import fr.ifremer.tutti.ichtyometer.feed.event.IchtyometerFeedReaderListener;
30  import fr.ifremer.tutti.ichtyometer.feed.record.IchtyometerFeedReaderMeasureRecord;
31  import fr.ifremer.tutti.ichtyometer.feed.record.IchtyometerFeedReaderRecordFactory;
32  import fr.ifremer.tutti.ichtyometer.feed.record.IchtyometerFeedReaderRecordSupport;
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  
36  import javax.microedition.io.StreamConnection;
37  import javax.swing.event.EventListenerList;
38  import java.io.Closeable;
39  import java.io.DataInputStream;
40  import java.io.IOException;
41  
42  /**
43   * To read some records from a ichtyometer in feed mode.
44   *
45   * Created on 1/24/14.
46   *
47   * @author Tony Chemit - chemit@codelutin.com
48   * @since 3.1
49   */
50  public class IchtyometerFeedReader implements Closeable {
51  
52      /** Logger. */
53      private static final Log log = LogFactory.getLog(IchtyometerFeedReader.class);
54  
55      /**
56       * Ichtyometer client given in the {@code start} method.
57       */
58      protected IchtyometerClient client;
59  
60      /**
61       * Reader runnable code (to be used in a thread).
62       */
63      protected ReadingRunnable readingRunnable;
64  
65      /**
66       * To keep list of {@link IchtyometerFeedReaderListener} listeners.
67       */
68      protected final EventListenerList listenerList;
69  
70      /**
71       * To generate some feed record from the rax record send by the board.
72       *
73       * @since 3.10
74       */
75      protected final IchtyometerFeedReaderRecordFactory recordFactory;
76  
77      public IchtyometerFeedReader() {
78          listenerList = new EventListenerList();
79          recordFactory = new IchtyometerFeedReaderRecordFactory();
80      }
81  
82      public void start(IchtyometerClient client) throws IOException {
83  
84          Preconditions.checkNotNull(client, "client can not be null");
85          Preconditions.checkState(client.isOpen(), "client must be opened");
86          this.client = client;
87  
88          // get connection
89          StreamConnection connection = client.openConnection();
90  
91          // get input stream
92          DataInputStream dataInputStream = connection.openDataInputStream();
93  
94          // create the reader runnable
95          readingRunnable = new ReadingRunnable(dataInputStream);
96  
97          // start the reader thread
98          new Thread(readingRunnable).start();
99  
100         if (log.isDebugEnabled()) {
101             log.debug("Ready to read remote device...");
102         }
103     }
104 
105     @Override
106     public void close() throws IOException {
107 
108         Preconditions.checkNotNull(client, "client can not be null");
109         Preconditions.checkState(client.isOpen(), "client must be opened");
110 
111         try {
112             readingRunnable.stop();
113 
114         } finally {
115 
116             Closeables.close(client, true);
117         }
118     }
119 
120     public String getClientName() {
121         return client.getName();
122     }
123 
124     public void addFeedModeReaderListener(IchtyometerFeedReaderListener listener) {
125         listenerList.add(IchtyometerFeedReaderListener.class, listener);
126     }
127 
128     public void removeFeedModeReaderListener(IchtyometerFeedReaderListener listener) {
129         listenerList.remove(IchtyometerFeedReaderListener.class, listener);
130     }
131 
132     public void removeAllFeedModeReaderListeners() {
133         for (IchtyometerFeedReaderListener listener : listenerList.getListeners(IchtyometerFeedReaderListener.class)) {
134             listenerList.remove(IchtyometerFeedReaderListener.class, listener);
135         }
136     }
137 
138     protected class ReadingRunnable implements Runnable {
139 
140         /**
141          * Input stream to read new record.
142          */
143         protected final DataInputStream dataInputStream;
144 
145         /**
146          * Flag to stop the runnable.
147          */
148         protected boolean stop;
149 
150         protected ReadingRunnable(DataInputStream dataInputStream) {
151             this.dataInputStream = dataInputStream;
152         }
153 
154         protected void stop() {
155             this.stop = true;
156         }
157 
158         @Override
159         public void run() {
160 
161             if (log.isInfoEnabled()) {
162                 log.info("Reader thread start... " + this);
163             }
164 
165             while (!stop) {
166 
167                 try {
168                     // get a new record
169                     IchtyometerFeedReaderRecordSupport readerRecord = readRecord(dataInputStream);
170 
171                     if (!stop && readerRecord != null && readerRecord instanceof IchtyometerFeedReaderMeasureRecord) {
172 
173                         // send new record to listeners
174                         IchtyometerFeedReaderEvent e = new IchtyometerFeedReaderEvent(IchtyometerFeedReader.this, (IchtyometerFeedReaderMeasureRecord) readerRecord);
175                         for (IchtyometerFeedReaderListener listener : listenerList.getListeners(IchtyometerFeedReaderListener.class)) {
176                             listener.recordRead(e);
177                         }
178                         
179                     }
180                 } catch (IOException e) {
181                     if (log.isErrorEnabled()) {
182                         log.error("Could not read record", e);
183                     }
184                 }
185             }
186 
187             if (log.isInfoEnabled()) {
188                 log.info("Reader thread stop..." + this);
189             }
190         }
191 
192         protected IchtyometerFeedReaderRecordSupport readRecord(DataInputStream dataInputStream) throws IOException {
193 
194             String result = "";
195 
196             // wait until got a #
197 
198             boolean complete = false;
199 
200             while (!complete) {
201 
202                 if (stop) {
203                     break;
204                 }
205                 while (dataInputStream.available() > 0) {
206                     if (complete || stop) {
207                         break;
208                     }
209                     int c = dataInputStream.read();
210 
211                     result += (char) c;
212 
213                     if ('#' == (char) c) {
214 
215                         complete = true;
216                     }
217                 }
218             }
219 
220             IchtyometerFeedReaderRecordSupport readerRecord = null;
221 
222             if (!stop) {
223 
224                 if (log.isInfoEnabled()) {
225                     log.info("New raw record: " + result);
226                 }
227                 readerRecord = recordFactory.newRecord(result);
228 
229                 if (log.isDebugEnabled()) {
230                     log.debug("New feed record: " + readerRecord);
231                 }
232 
233             }
234 
235             return readerRecord;
236         }
237     }
238 }