r357 - in trunk: sammoa-application/src/main/java sammoa-application/src/main/java/fr/ulr/sammoa/application sammoa-application/src/main/java/fr/ulr/sammoa/application/audio sammoa-application/src/main/java/fr/ulr/sammoa/application/gps sammoa-application/src/main/java/gnu sammoa-application/src/main/java/gnu/io sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/layer sa
Author: fdesbois Date: 2012-08-06 16:33:43 +0200 (Mon, 06 Aug 2012) New Revision: 357 Url: http://forge.codelutin.com/repositories/revision/sammoa/357 Log: refs #1378 : Improve Device management for GPS and Audio, use proper API and errors Added: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceManager.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceTechnicalException.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceUpdateEvent.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceUpdateListener.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/SammoaGPSSerialDevice.java trunk/sammoa-application/src/main/java/gnu/ trunk/sammoa-application/src/main/java/gnu/io/ trunk/sammoa-application/src/main/java/gnu/io/RXTXHack.java Removed: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioUpdateListener.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/AudioStateLED.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/GpsStateLED.java Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightController.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightControllerDefault.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/SammoaContext.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorder.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorderDefault.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorderMock.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/BaseGpsHandler.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/FakeGpsHandler.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsHandler.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsHandlerGpsylon.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsUpdateListener.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/MainUIHandler.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/DeviceStateLED.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBar.jaxx trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBarHandler.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBarModel.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightUIHandler.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/layer/GpsTracingLayer.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/EffortPanelHandler.java trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/util/SammoaUtil.java Added: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceManager.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceManager.java (rev 0) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceManager.java 2012-08-06 14:33:43 UTC (rev 357) @@ -0,0 +1,80 @@ +package fr.ulr.sammoa.application; +/* + * #%L + * SAMMOA :: Application + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2012 UMS 3462, Code Lutin + * %% + * This program 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. + * + * This program 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 this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import java.util.Set; + +/** + * Created: 06/08/12 + * + * @author fdesbois <florian.desbois@codelutin.com> + */ +public interface DeviceManager<L extends DeviceUpdateListener> { + + /** + * Open the device + * + * @throws DeviceTechnicalException for errors on open + */ + void open() throws DeviceTechnicalException; + + /** + * Start the device session (recording, reading, ...) and try opening it if necessary. The open + * could be tried several times to permit a proper start. + */ + void start(); + + /** + * Stop the device session + */ + void stop(); + + /** + * Close the device and stop it if necessary + * + * @throws DeviceTechnicalException for errors on close + */ + void close() throws DeviceTechnicalException; + + /** + * @return the DeviceState + */ + DeviceState getState(); + + /** + * @param listener DeviceUpdateListener to add + */ + void addUpdateListener(L listener); + + /** + * @param listener DeviceUpdateListener to remove + */ + void removeUpdateListener(L listener); + + /** + * @return all the listeners + */ + Set<L> getUpdateListeners(); + +} Property changes on: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceManager.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceTechnicalException.java (from rev 356, trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/AudioStateLED.java) =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceTechnicalException.java (rev 0) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceTechnicalException.java 2012-08-06 14:33:43 UTC (rev 357) @@ -0,0 +1,49 @@ +/* + * #%L + * SAMMOA :: Application + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 UMS 3462, Code Lutin + * %% + * This program 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. + * + * This program 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 this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ulr.sammoa.application; + +/** + * @author fdesbois <fdesbois@codelutin.com> + */ +public class DeviceTechnicalException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + protected DeviceManager source; + + public DeviceTechnicalException(DeviceManager source, String message) { + super(message); + this.source = source; + } + + public DeviceTechnicalException(DeviceManager source, String message, Throwable cause) { + super(message, cause); + this.source = source; + } + + public DeviceManager getSource() { + return source; + } +} Property changes on: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceTechnicalException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceUpdateEvent.java (from rev 356, trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioUpdateListener.java) =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceUpdateEvent.java (rev 0) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceUpdateEvent.java 2012-08-06 14:33:43 UTC (rev 357) @@ -0,0 +1,56 @@ +package fr.ulr.sammoa.application; +/* + * #%L + * SAMMOA :: Application + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2012 UMS 3462, Code Lutin + * %% + * This program 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. + * + * This program 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 this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Created: 06/08/12 + * + * @author fdesbois <florian.desbois@codelutin.com> + */ +public class DeviceUpdateEvent<T> { + + protected DeviceManager source; + + protected T oldValue; + + protected T newValue; + + public DeviceUpdateEvent(DeviceManager source, T oldValue, T newValue) { + this.source = source; + this.oldValue = oldValue; + this.newValue = newValue; + } + + public DeviceManager getSource() { + return source; + } + + public T getOldValue() { + return oldValue; + } + + public T getNewValue() { + return newValue; + } +} \ No newline at end of file Copied: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceUpdateListener.java (from rev 356, trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioUpdateListener.java) =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceUpdateListener.java (rev 0) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/DeviceUpdateListener.java 2012-08-06 14:33:43 UTC (rev 357) @@ -0,0 +1,39 @@ +package fr.ulr.sammoa.application; +/* + * #%L + * SAMMOA :: Application + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2012 UMS 3462, Code Lutin + * %% + * This program 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. + * + * This program 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 this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Created: 06/08/12 + * + * @author fdesbois <florian.desbois@codelutin.com> + */ +public interface DeviceUpdateListener { + + /** + * Update device state. + * + * @param event new event + */ + void onStateChanged(DeviceUpdateEvent<DeviceState> event); +} Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightController.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightController.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightController.java 2012-08-06 14:33:43 UTC (rev 357) @@ -66,10 +66,16 @@ /** * @param config GpsConfig to initialize the Gps + * @exception DeviceTechnicalException if the gps device can't be opened properly */ - void initGpsHandler(GpsConfig config); + void openGpsDevice(GpsConfig config) throws DeviceTechnicalException; /** + * @exception DeviceTechnicalException if the audio device can't be opened properly + */ + void openAudioDevice() throws DeviceTechnicalException; + + /** * @return The current {@link Route} */ Route getCurrentRoute(); @@ -80,6 +86,15 @@ TransectFlight getNextTransect(); /** + * Initialize all data of FlightController depends on the current flight state. + * If the flight is running ({@link #isRunning()}), the devices will be started and + * recording if necessary. + * <p/> + * You must call init method to ensure the {@link FlightState}. + */ + void init(); + + /** * Start operation. This will set the {@code beginDate} of the flight, then * a new {@link RouteType#TRANSIT} route is created. The state is now * {@link FlightState#OFF_EFFORT}. Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightControllerDefault.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightControllerDefault.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/FlightControllerDefault.java 2012-08-06 14:33:43 UTC (rev 357) @@ -25,9 +25,11 @@ package fr.ulr.sammoa.application; import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; import com.google.common.base.Throwables; import com.google.common.collect.Sets; import fr.ulr.sammoa.application.audio.AudioRecorder; +import fr.ulr.sammoa.application.audio.AudioRecorderDefault; import fr.ulr.sammoa.application.gps.GpsConfig; import fr.ulr.sammoa.application.gps.GpsHandler; import fr.ulr.sammoa.application.gps.GpsUpdateListener; @@ -66,7 +68,7 @@ */ public class FlightControllerDefault implements GpsUpdateListener, FlightController { - private static final Logger logger = LoggerFactory.getLogger(FlightService.class); + private static final Logger logger = LoggerFactory.getLogger(FlightControllerDefault.class); private static final TimeLog timeLog = new TimeLog(FlightControllerDefault.class, 500, 1000); @@ -80,6 +82,8 @@ protected GpsHandler gpsHandler; + protected boolean initialized; + protected FlightState state; protected Flight flight; @@ -98,19 +102,12 @@ this.context = context; this.flight = flight; - GpsConfig gpsConfig = context.getConfig().getGpsConfig(); - initGpsHandler(gpsConfig); - - this.audioRecorder = context.getAudioRecorder(); - this.persistence = context.getPersistence(); this.service = context.getFlightService(); this.currentRoute = service.getLastRoute(flight); this.lastTransect = service.getLastTransectDone(flight); this.listeners = Sets.newHashSet(); - - init(); } @Override @@ -149,49 +146,59 @@ } @Override - public void initGpsHandler(GpsConfig config) { + public void openGpsDevice(final GpsConfig config) throws DeviceTechnicalException { - Set<GpsUpdateListener> updateListeners; - if (gpsHandler != null) { + gpsHandler = newDeviceManager(gpsHandler, new Supplier<GpsHandler>() { - // Remove all existing listeners and keep them for the new instance - updateListeners = Sets.newHashSet(gpsHandler.getGpsUpdateListeners()); - for (GpsUpdateListener listener : updateListeners) { - gpsHandler.removeGpsUpdateListener(listener); + @Override + public GpsHandler get() { + + // Instanciate the GpsHandler + Class<? extends GpsHandler> gpsHandlerClass = config.getGpsHandlerClass(); + try { + + Constructor<? extends GpsHandler> constructor = + gpsHandlerClass.getConstructor(GpsConfig.class); + + GpsHandler result = constructor.newInstance(config); + result.addUpdateListener(FlightControllerDefault.this); + return result; + + } catch (InstantiationException e) { + throw Throwables.propagate(e); + } catch (IllegalAccessException e) { + throw Throwables.propagate(e); + } catch (NoSuchMethodException e) { + throw Throwables.propagate(e); + } catch (InvocationTargetException e) { + throw Throwables.propagate(e); + } } + }); + if (initialized && isRunning()) { + gpsHandler.start(); } else { - updateListeners = Sets.<GpsUpdateListener>newHashSet(this); + gpsHandler.open(); } + } - // Instanciate the GpsHandler - Class<? extends GpsHandler> gpsHandlerClass = config.getGpsHandlerClass(); - try { + @Override + public void openAudioDevice() throws DeviceTechnicalException { - Constructor<? extends GpsHandler> constructor = - gpsHandlerClass.getConstructor(GpsConfig.class); + audioRecorder = newDeviceManager(audioRecorder, new Supplier<AudioRecorder>() { - gpsHandler = constructor.newInstance(config); + @Override + public AudioRecorder get() { + return new AudioRecorderDefault(); + } + }); - } catch (InstantiationException e) { - throw Throwables.propagate(e); - } catch (IllegalAccessException e) { - throw Throwables.propagate(e); - } catch (NoSuchMethodException e) { - throw Throwables.propagate(e); - } catch (InvocationTargetException e) { - throw Throwables.propagate(e); + if (initialized && isRunning()) { + audioRecorder.start(); + } else { + audioRecorder.open(); } - - // Attach all updateListener - for (GpsUpdateListener listener : updateListeners) { - gpsHandler.addGpsUpdateListener(listener); - } - - // Start the GpsHandler if Flight is running - if (isRunning()) { - gpsHandler.start(); - } } @Override @@ -220,22 +227,89 @@ } @Override + public void init() { + + Preconditions.checkState(gpsHandler != null, + "The GpsHandler must be created using #openGpsDevice"); + + Preconditions.checkState(audioRecorder != null, + "The AudioRecorder must be created using #openAudioDevice"); + + if (initialized) { + if (logger.isWarnEnabled()) { + logger.warn("The FlightController is already initialized"); + } + return; + } + + if (logger.isInfoEnabled()) { + logger.info("Initialize the FlightController for flight " + flight.getFlightNumber()); + } + + initialized = true; + + // Note that a flight can't finished by a leg, so effort not null + // implies that the flight is started and not ended + if (currentRoute != null + && currentRoute.getRouteType() == RouteType.LEG) { + + state = FlightState.ON_EFFORT; + + } else if (currentRoute != null + && flight.getBeginDate() != null + && flight.getEndDate() == null) { + + state = FlightState.OFF_EFFORT; + + } else if (flight.getEndDate() != null) { + + state = FlightState.ENDED; + + } else { + state = FlightState.WAITING; + } + + if (isRunning()) { + + gpsHandler.start(); + + audioRecorder.start(); + + // Selection of the nextTransect, keep the last one for circleBack + if (currentRoute.getRouteType() == RouteType.CIRCLE_BACK) { + nextTransect = lastTransect; + + } else { + nextTransect = flight.getNextTransectFlightFrom(lastTransect); + } + + // Restart recording audio if onEffort or circleBack + if (state == FlightState.ON_EFFORT + || currentRoute.getRouteType() == RouteType.CIRCLE_BACK) { + + saveAudio(0); + } + } + } + + @Override public void start() { long startTime = TimeLog.getTime(); + Preconditions.checkState(initialized, + "The controller must be initialized before calling any action"); + Preconditions.checkState( isWaiting(), "You can call start() only if flight is waiting (not started, not ended)"); - // Start gps - getGpsHandler().start(); + gpsHandler.start(); - // Start audio - getAudioRecorder().start(); + audioRecorder.start(); TopiaContext transaction = persistence.beginTransaction(); try { - + Date currentDate = saveGPS(transaction, gpsHandler.getCurrentLocation(), flight); setFlightBeginDate(transaction, flight, currentDate); @@ -265,10 +339,10 @@ fireStateChanged(state); timeLog.log(startTime, "start()", "Fired"); - + } catch (TopiaException e) { throw new TopiaRuntimeException(e); - + } finally { persistence.endTransaction(transaction); } @@ -279,6 +353,9 @@ long startTime = TimeLog.getTime(); + Preconditions.checkState(initialized, + "The controller must be initialized before calling any action"); + Preconditions.checkState( nextTransect == null || !nextTransect.isDeleted(), "You can't use a deleted transect as next value"); @@ -295,6 +372,9 @@ long startTime = TimeLog.getTime(); + Preconditions.checkState(initialized, + "The controller must be initialized before calling any action"); + Preconditions.checkState( isOffEffort(), "You can call begin() only if flight is running (started, not ended, not on effort)"); @@ -348,6 +428,9 @@ long startTime = TimeLog.getTime(); + Preconditions.checkState(initialized, + "The controller must be initialized before calling any action"); + Preconditions.checkState( currentRoute != null && currentRoute.getRouteType() != RouteType.TRANSIT, @@ -399,6 +482,9 @@ long startTime = TimeLog.getTime(); + Preconditions.checkState(initialized, + "The controller must be initialized before calling any action"); + Preconditions.checkState( isOnEffort(), "You can call add() only if flight is on effort (started, not ended, on effort)"); @@ -451,6 +537,9 @@ long startTime = TimeLog.getTime(); + Preconditions.checkState(initialized, + "The controller must be initialized before calling any action"); + Preconditions.checkState( isRunning(), "You can call observation() only if flight is running (started, not ended)"); @@ -513,6 +602,9 @@ long startTime = TimeLog.getTime(); + Preconditions.checkState(initialized, + "The controller must be initialized before calling any action"); + Preconditions.checkState( isOffEffort(), "You can call stop() only if flight is running (started, not ended, not on effort)"); @@ -561,13 +653,21 @@ @Override public void close() { - getAudioRecorder().stop(); - getGpsHandler().stop(); + + audioRecorder.close(); + audioRecorder = null; + + gpsHandler.close(); + gpsHandler = null; + persistence.stopAutoSaveListener(); } protected void doEndWithAudioDelay(long audioDelay) { + Preconditions.checkState(initialized, + "The controller must be initialized before calling any action"); + Preconditions.checkState( isOnEffort(), "You can call end() only if flight is on effort (started, not ended, on effort)"); @@ -600,54 +700,6 @@ } } - protected void init() { - - // Note that a flight can't finished by a leg, so effort not null - // implies that the flight is started and not ended - if (currentRoute != null - && currentRoute.getRouteType() == RouteType.LEG) { - - state = FlightState.ON_EFFORT; - - } else if (currentRoute != null - && flight.getBeginDate() != null - && flight.getEndDate() == null) { - - state = FlightState.OFF_EFFORT; - - } else if (flight.getEndDate() != null) { - - state = FlightState.ENDED; - - } else { - state = FlightState.WAITING; - } - - if (isRunning()) { - - // Start gps - getGpsHandler().start(); - - // Start audio - getAudioRecorder().start(); - - // Selection of the nextTransect, keep the last one for circleBack - if (currentRoute.getRouteType() == RouteType.CIRCLE_BACK) { - nextTransect = lastTransect; - - } else { - nextTransect = flight.getNextTransectFlightFrom(lastTransect); - } - - // Restart recording audio if onEffort or circleBack - if (state == FlightState.ON_EFFORT - || currentRoute.getRouteType() == RouteType.CIRCLE_BACK) { - - saveAudio(0); - } - } - } - // protected void setNextTransect(TransectFlight nextTransect, boolean fireEvents) { // // this.nextTransect = nextTransect; @@ -766,8 +818,37 @@ } } + protected <T extends DeviceManager> T newDeviceManager(T oldInstance, Supplier<T> supplier) + throws DeviceTechnicalException { + + Set<DeviceUpdateListener> updateListeners; + if (oldInstance != null) { + + // Remove all existing listeners and keep them for the new instance + updateListeners = Sets.newHashSet(oldInstance.getUpdateListeners()); + for (DeviceUpdateListener listener : updateListeners) { + oldInstance.removeUpdateListener(listener); + } + + oldInstance.close(); + + } else { + updateListeners = Sets.newHashSet(); + } + + T result = supplier.get(); + + // Attach all updateListener + for (DeviceUpdateListener listener : updateListeners) { + result.addUpdateListener(listener); + } + + return result; + } + @Override - public void onLocationReceived(GeoPoint newLocation) { + public void onLocationReceived(DeviceUpdateEvent<GeoPoint> event) { + GeoPoint newLocation = event.getNewValue(); if (newLocation != null/* && newLocation.getTopiaId() == null*/) { newLocation.setFlight(flight); persistence.delayEntityCreation(newLocation); @@ -775,7 +856,8 @@ } @Override - public void onStateChanged(DeviceState state) { + public void onStateChanged(DeviceUpdateEvent<DeviceState> event) { + // nothing to do } } Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/SammoaContext.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/SammoaContext.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/SammoaContext.java 2012-08-06 14:33:43 UTC (rev 357) @@ -24,8 +24,6 @@ */ package fr.ulr.sammoa.application; -import fr.ulr.sammoa.application.audio.AudioRecorder; -import fr.ulr.sammoa.application.audio.AudioRecorderDefault; import fr.ulr.sammoa.application.map.ExportMapService; import fr.ulr.sammoa.persistence.SammoaPersistence; @@ -48,8 +46,6 @@ protected ExportMapService exportMapService; - protected AudioRecorder audioRecorder; - public SammoaContext(SammoaConfig config) { this(config, new SammoaPersistence( config.getApplicationConfig().getFlatOptions(), @@ -70,13 +66,6 @@ return persistence; } - public AudioRecorder getAudioRecorder() { - if (audioRecorder == null) { - audioRecorder = new AudioRecorderDefault(); - } - return audioRecorder; - } - public FlightService getFlightService() { if (flightService == null) { flightService = new FlightService(this); Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorder.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorder.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorder.java 2012-08-06 14:33:43 UTC (rev 357) @@ -23,7 +23,8 @@ * #L% */ -import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceManager; +import fr.ulr.sammoa.application.DeviceUpdateListener; import javax.sound.sampled.AudioFileFormat; import java.io.File; @@ -37,25 +38,14 @@ * * @author fdesbois <desbois@codelutin.com> */ -public interface AudioRecorder { +public interface AudioRecorder extends DeviceManager<DeviceUpdateListener> { /** - * @return current {@link DeviceState} - */ - DeviceState getState(); - - /** * @return the {@link AudioFileFormat.Type} used (default is WAV) */ AudioFileFormat.Type getOutputType(); /** - * Start the recorder. This will open the audio line. No recorders are - * running yet. - */ - void start(); - - /** * Record the audio line and save the data in given {@code outputFile}. The * previous recording will be stopped in {@code delaySeconds}. The delay is * useful to avoid recording lost or too quick between two files. @@ -72,19 +62,4 @@ * @param delaySeconds Delay for current recording */ void stopRecord(long delaySeconds); - - /** - * Stop the recorder. This will flush data in recorders and close the line. - */ - void stop(); - - /** - * @param listener AudioUpdateListener to add - */ - void addAudioUpdateListener(AudioUpdateListener listener); - - /** - * @param listener AudioUpdateListener to remove - */ - void removeAudioUpdateListener(AudioUpdateListener listener); } Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorderDefault.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorderDefault.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorderDefault.java 2012-08-06 14:33:43 UTC (rev 357) @@ -29,13 +29,32 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceTechnicalException; +import fr.ulr.sammoa.application.DeviceUpdateEvent; +import fr.ulr.sammoa.application.DeviceUpdateListener; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.sound.sampled.*; -import java.io.*; -import java.util.*; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.TargetDataLine; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; /** * Created: 16/05/12 @@ -81,7 +100,7 @@ protected DeviceState state; - protected Set<AudioUpdateListener> listeners; + protected Set<DeviceUpdateListener> listeners; public AudioRecorderDefault() { this(new AudioFormat( @@ -111,11 +130,12 @@ } protected void setState(DeviceState state) { + DeviceState oldValue = getState(); this.state = state; // Fire on listeners - for (AudioUpdateListener listener : listeners) { - listener.onStateChanged(state); + for (DeviceUpdateListener listener : listeners) { + listener.onStateChanged(new DeviceUpdateEvent<DeviceState>(this, oldValue, state)); } } @@ -125,22 +145,26 @@ } @Override - public void addAudioUpdateListener(AudioUpdateListener listener) { + public void addUpdateListener(DeviceUpdateListener listener) { listeners.add(listener); } @Override - public void removeAudioUpdateListener(AudioUpdateListener listener) { + public void removeUpdateListener(DeviceUpdateListener listener) { listeners.remove(listener); } @Override - public void start() { + public Set<DeviceUpdateListener> getUpdateListeners() { + return listeners; + } - // Stop previous recording - stop(); + @Override + public void open() throws DeviceTechnicalException { - logger.info("Open the audio line"); + if (logger.isInfoEnabled()) { + logger.info("Open the audio line"); + } DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat); try { @@ -150,24 +174,55 @@ // Start using the line for recording dataLine.start(); - lineReader = new DataLineReader(); - lineReader.start(); - setState(DeviceState.READY); - } catch (Exception e) { - logger.error("Can't start recording", e); - setState(DeviceState.NO_DATA); + if (logger.isInfoEnabled()) { + logger.info("Audio line is ready"); + } + + } catch (IllegalArgumentException e) { + setState(DeviceState.NO_DEVICE); + throw new DeviceTechnicalException(this, "Can't open audio device", e); + + } catch (IllegalStateException e) { + setState(DeviceState.NO_DEVICE); + throw new DeviceTechnicalException(this, "Can't open audio device", e); + + } catch (SecurityException e) { + setState(DeviceState.NO_DEVICE); + throw new DeviceTechnicalException(this, "Can't open audio device", e); + + } catch (LineUnavailableException e) { + setState(DeviceState.NO_DEVICE); + throw new DeviceTechnicalException(this, "Can't open audio device", e); } } @Override + public void start() { + + if (getState() == DeviceState.READY) { + + // Stop previous recording + stop(); + + logger.info("Start reading audio line"); + + lineReader = new DataLineReader(); + lineReader.start(); + } + } + + @Override public void record(File outputFile, long delaySeconds) throws IOException { if (DeviceState.NO_DATA == state) { if (logger.isWarnEnabled()) { logger.warn("Can't record " + outputFile.getAbsolutePath() + ", no available dataLine"); } + + // XXX-fdesbois-2012-08-03 : try to start the line again ? + return; } @@ -220,16 +275,25 @@ @Override public void stop() { - if (dataLine != null && dataLine.isRunning()) { + if (getState() != DeviceState.NO_DEVICE) { - logger.info("Close the audio line"); - // Destroy the thread if (lineReader != null) { lineReader.interrupt(); } lineReader = null; + } + } + @Override + public void close() throws DeviceTechnicalException { + + stop(); + + if (dataLine != null && dataLine.isRunning()) { + + logger.info("Close the audio line"); + dataLine.stop(); dataLine.drain(); dataLine.close(); Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorderMock.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorderMock.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioRecorderMock.java 2012-08-06 14:33:43 UTC (rev 357) @@ -23,11 +23,15 @@ * #L% */ +import com.google.common.collect.Sets; import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceTechnicalException; +import fr.ulr.sammoa.application.DeviceUpdateListener; import javax.sound.sampled.AudioFileFormat; import java.io.File; import java.io.IOException; +import java.util.Set; /** * Mock for {@link AudioRecorder} that record nothing. @@ -49,6 +53,11 @@ } @Override + public void open() throws DeviceTechnicalException { + // do nothing + } + + @Override public void start() { // do nothing } @@ -69,12 +78,22 @@ } @Override - public void addAudioUpdateListener(AudioUpdateListener listener) { + public void close() throws DeviceTechnicalException { // do nothing } @Override - public void removeAudioUpdateListener(AudioUpdateListener listener) { + public void addUpdateListener(DeviceUpdateListener listener) { // do nothing } + + @Override + public void removeUpdateListener(DeviceUpdateListener listener) { + // do nothing + } + + @Override + public Set<DeviceUpdateListener> getUpdateListeners() { + return Sets.newHashSet(); + } } Deleted: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioUpdateListener.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioUpdateListener.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioUpdateListener.java 2012-08-06 14:33:43 UTC (rev 357) @@ -1,42 +0,0 @@ -/* - * #%L - * SAMMOA :: Application - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2012 UMS 3462, Code Lutin - * %% - * This program 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. - * - * This program 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 this program. If not, see - * <http://www.gnu.org/licenses/gpl-3.0.html>. - * #L% - */ -package fr.ulr.sammoa.application.audio; - -import fr.ulr.sammoa.application.DeviceState; - -/** - * Created: 15/06/12 - * - * @author fdesbois <desbois@codelutin.com> - */ -public interface AudioUpdateListener { - - /** - * Update audio line state. - * - * @param state new state - */ - void onStateChanged(DeviceState state); - -} Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/BaseGpsHandler.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/BaseGpsHandler.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/BaseGpsHandler.java 2012-08-06 14:33:43 UTC (rev 357) @@ -25,7 +25,11 @@ import com.google.common.collect.Sets; import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceTechnicalException; +import fr.ulr.sammoa.application.DeviceUpdateEvent; import fr.ulr.sammoa.persistence.GeoPoint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Set; import java.util.Timer; @@ -33,11 +37,11 @@ /** * Base class for {@link GpsHandler} interface. This class contains common behaviour - * for automatic check on a given {@code period}. For that, this class act - * as a {@link TimerTask} scheduled from constructor. You can override the - * method {@link #onInit()} to add some initialize behaviour before running - * the Timer thread. The method {@link #getCurrentLocation()} must return - * null if the location doesn't change or the GPS is down. + * for automatic check on a given {@code period}. For that, this class contains + * a {@link TimerTask} scheduled from {@link #start()}. The {@link #open()} method + * will be called on start if state is still {@link DeviceState#NO_DEVICE}. + * The method {@link #getCurrentLocation()} must return null if the location doesn't + * change or the GPS is down. * * Created: 02/07/12 * @@ -46,40 +50,35 @@ * @see FakeGpsHandler * @see GpsHandlerGpsylon */ -public abstract class BaseGpsHandler extends TimerTask implements GpsHandler { +public abstract class BaseGpsHandler implements GpsHandler { + private static final Logger logger = LoggerFactory.getLogger(BaseGpsHandler.class); + protected Set<GpsUpdateListener> gpsUpdateListeners; /** To test if connection to device is effective. */ - protected DeviceState gpsState = DeviceState.NO_DEVICE; + protected DeviceState state; - /** To test if UI has activated gps position tracking. */ - protected boolean trackingStarted; + protected GpsConfig config; + protected Timer timer; + /** * Value to check the number of timer update failures before the DeviceState * becomes {@link DeviceState#NO_DATA} */ protected int nbFailuresMax; - protected int nbFailures; - - protected GpsConfig config; - public BaseGpsHandler(GpsConfig config) { this.config = config; - int periodSeconds = config.getCheckPeriod(); - int timeoutSeconds = config.getTimeout(); - gpsUpdateListeners = Sets.newHashSet(); + this.state = DeviceState.NO_DEVICE; + this.gpsUpdateListeners = Sets.newHashSet(); + this.nbFailuresMax = + (int) Math.ceil(config.getTimeout() / config.getCheckPeriod()); - onInit(); - - nbFailuresMax = (int) Math.ceil(timeoutSeconds / periodSeconds); - - // un thread doit tourner tout le temps et dès le départ pour - // vérifier un changement d'état du gps - Timer gpsStatusTimer = new Timer(); - gpsStatusTimer.schedule(this, 0, periodSeconds * 1000); + if (logger.isDebugEnabled()) { + logger.debug("GPS NbFailuresMax = " + nbFailuresMax); + } } public GpsConfig getConfig() { @@ -87,77 +86,122 @@ } @Override - public void start() { - trackingStarted = true; + public DeviceState getState() { + return state; } @Override + public void start() throws DeviceTechnicalException { + + long periodMilliseconds = config.getCheckPeriod() * 1000; + + if (getState() == DeviceState.READY) { + + if (logger.isDebugEnabled()) { + logger.debug("Start scheduling GpsHandler every " + + periodMilliseconds + " milliseconds"); + } + + timer = new Timer(); + timer.schedule(recordTask, 0, periodMilliseconds); + + } else { + + timer = new Timer(); + timer.schedule(openTask, 0, periodMilliseconds); + } + } + + @Override public void stop() { - trackingStarted = false; + timer.cancel(); + timer = null; } @Override - public void addGpsUpdateListener(GpsUpdateListener gpsUpdateListener) { + public void addUpdateListener(GpsUpdateListener gpsUpdateListener) { gpsUpdateListeners.add(gpsUpdateListener); } @Override - public void removeGpsUpdateListener(GpsUpdateListener gpsUpdateListener) { + public void removeUpdateListener(GpsUpdateListener gpsUpdateListener) { gpsUpdateListeners.remove(gpsUpdateListener); } @Override - public Set<GpsUpdateListener> getGpsUpdateListeners() { + public Set<GpsUpdateListener> getUpdateListeners() { return gpsUpdateListeners; } - @Override - public void run() { + protected void setState(DeviceState state) { + DeviceState oldValue = getState(); + this.state = state; - GeoPoint currentLocation = getCurrentLocation(); + for (GpsUpdateListener listener : gpsUpdateListeners) { + listener.onStateChanged(new DeviceUpdateEvent<DeviceState>(this, oldValue, state)); + } + } - // increment nbFailures if currentLocation is undefined - if (currentLocation == null) { - nbFailures++; - }else { - nbFailures = 0; + protected TimerTask openTask = new TimerTask() { + + @Override + public void run() { + try { + + open(); + + timer.cancel(); + timer = null; + + start(); + + } catch (DeviceTechnicalException ex) { + + // We use NO_DATA, because this task is during start + setState(DeviceState.NO_DATA); + + if (logger.isErrorEnabled()) { + logger.error("Can't open GPS device. Try again in " + + this.scheduledExecutionTime() + " milliseconds", ex); + } + } } + }; - if (trackingStarted) { + protected TimerTask recordTask = new TimerTask() { + protected GeoPoint location; + + protected int nbFailures; + + @Override + public void run() { + + GeoPoint lastLocation = location; + + location = getCurrentLocation(); + + // reset nbFailures if currentLocation is defined + if (location != null) { + nbFailures = 0; + } else { + nbFailures++; + } + // Data is unavailable - if (currentLocation == null && nbFailures >= nbFailuresMax) { - setGpsState(DeviceState.NO_DATA); + if (location == null && nbFailures >= nbFailuresMax) { + setState(DeviceState.NO_DATA); // GPS is recording } else { - setGpsState(DeviceState.RECORDING); + setState(DeviceState.RECORDING); // Fire events for location change for (GpsUpdateListener listener : gpsUpdateListeners) { - listener.onLocationReceived(currentLocation); + listener.onLocationReceived(new DeviceUpdateEvent<GeoPoint>(BaseGpsHandler.this, lastLocation, location)); } } - - // GPS is unavailable - } else if (currentLocation == null && nbFailures >= nbFailuresMax) { - setGpsState(DeviceState.NO_DEVICE); - - // GPS is ready - } else { - setGpsState(DeviceState.READY); } - } - - protected void setGpsState(DeviceState gpsState) { - this.gpsState = gpsState; - - for (GpsUpdateListener listener : gpsUpdateListeners) { - listener.onStateChanged(gpsState); - } - } - - protected void onInit() { - } + }; } Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/FakeGpsHandler.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/FakeGpsHandler.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/FakeGpsHandler.java 2012-08-06 14:33:43 UTC (rev 357) @@ -24,6 +24,7 @@ */ package fr.ulr.sammoa.application.gps; +import fr.ulr.sammoa.application.DeviceTechnicalException; import fr.ulr.sammoa.persistence.GeoPoint; import fr.ulr.sammoa.persistence.GeoPointImpl; import org.slf4j.Logger; @@ -89,8 +90,13 @@ // } // }, 10000, 10000); } - + @Override + public void open() throws DeviceTechnicalException { + // nothing to do + } + + @Override public void start() { if (thread == null) { thread = new Thread(new GpsPointGenerator()); @@ -100,6 +106,11 @@ } @Override + public void close() throws DeviceTechnicalException { + // nothing to do + } + + @Override protected void finalize() throws Throwable { if (thread != null) { Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsHandler.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsHandler.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsHandler.java 2012-08-06 14:33:43 UTC (rev 357) @@ -24,53 +24,19 @@ */ package fr.ulr.sammoa.application.gps; +import fr.ulr.sammoa.application.DeviceManager; import fr.ulr.sammoa.persistence.GeoPoint; -import java.util.Set; - /** * Représente l'accès à un périphérique GPS. */ -public interface GpsHandler { +public interface GpsHandler extends DeviceManager<GpsUpdateListener> { /** - * Démarre le tracking de position. - * Active la notification de la position via {@link GpsUpdateListener#onLocationReceived(GeoPoint)}. - */ - void start(); - - /** - * Stoppe le tracking de position. - * Désactive la notification de la position via {@link GpsUpdateListener#onLocationReceived(GeoPoint)}. - */ - void stop(); - - /** * Retourne la position courante du GPS. * * @return la position courante selon le GPS ou {@code null} si elle ne peut * pas être obtenue */ GeoPoint getCurrentLocation(); - - /** - * Permet de s'enregistrer pour écouter un événement levé - * lorsqu'un déplacement est mesuré par le GPS. - * - * @param gpsUpdateListener l'objet à notifier - */ - void addGpsUpdateListener(GpsUpdateListener gpsUpdateListener); - - /** - * Permet de se désenregistrer pour ne plus écouter les événements levés - * lorsqu'un déplacement est mesuré par le GPS. - * - * @param gpsUpdateListener l'objet à ne plus notifier - */ - void removeGpsUpdateListener(GpsUpdateListener gpsUpdateListener); - - /** - * @return all the listeners - */ - Set<GpsUpdateListener> getGpsUpdateListeners(); } Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsHandlerGpsylon.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsHandlerGpsylon.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsHandlerGpsylon.java 2012-08-06 14:33:43 UTC (rev 357) @@ -26,9 +26,11 @@ package fr.ulr.sammoa.application.gps; import com.google.common.base.Objects; -import fr.ulr.sammoa.application.SammoaTechnicalException; +import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceTechnicalException; import fr.ulr.sammoa.persistence.GeoPoint; import fr.ulr.sammoa.persistence.GeoPointImpl; +import gnu.io.CommPortIdentifier; import org.dinopolis.gpstool.gpsinput.GPSDataProcessor; import org.dinopolis.gpstool.gpsinput.GPSDevice; import org.dinopolis.gpstool.gpsinput.GPSException; @@ -41,6 +43,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Date; +import java.util.Enumeration; import java.util.Hashtable; /** @@ -48,25 +51,14 @@ * * @author echatellier */ -public class GpsHandlerGpsylon extends BaseGpsHandler implements PropertyChangeListener { +public class GpsHandlerGpsylon extends BaseGpsHandler { private static final Logger logger = LoggerFactory.getLogger(GpsHandlerGpsylon.class); -// protected Set<GpsUpdateListener> gpsUpdateListeners; - protected GPSDataProcessor gpsDataProcessor; protected GPSDevice gpsDevice; -// /** To test if connection to device is effective. */ -// protected DeviceState gpsState = DeviceState.NO_DEVICE; -// -// /** To test if UI has activated gps position tracking. */ -// protected boolean trackingStarted; - - /** Time stamp of last data received from gps. */ - protected long lastDataReceivedTimeStamp; - protected GPSPosition lastPosition; protected GPSPosition lastSendPosition; @@ -75,48 +67,131 @@ protected float lastSpeed; + protected boolean deviceInitialized; + public GpsHandlerGpsylon(GpsConfig config) { super(config); } @Override - protected void onInit() { - gpsDataProcessor = new GPSNmeaDataProcessor(); - // not usefull, processed by GPSNmeaDataProcessor - // and dispatched to GPSDataChangeListener - //gpsDataProcessor.addGPSRawDataListener(this); + public void open() throws DeviceTechnicalException { - // listen for specific properties - gpsDataProcessor.addGPSDataChangeListener(GPSDataProcessor.LOCATION, this); - gpsDataProcessor.addGPSDataChangeListener(GPSDataProcessor.ALTITUDE, this); - gpsDataProcessor.addGPSDataChangeListener(GPSDataProcessor.SPEED, this); + if (getState() == DeviceState.READY) { + if (logger.isWarnEnabled()) { + logger.warn("GPS already opened"); + } + return; + } - gpsDevice = new GPSSerialDevice(); try { - Hashtable<String, Object> options = new Hashtable<String, Object>(); - options.put(GPSSerialDevice.PORT_NAME_KEY, getConfig().getDevice()); - options.put(GPSSerialDevice.PORT_SPEED_KEY, getConfig().getSpeed()); - if (logger.isDebugEnabled()) { - logger.debug("GPS options: " + options); + if (!deviceInitialized) { + + gpsDataProcessor = new GPSNmeaDataProcessor(); + + gpsDevice = new SammoaGPSSerialDevice(); + + Hashtable<String, Object> options = new Hashtable<String, Object>(); + options.put(GPSSerialDevice.PORT_NAME_KEY, getConfig().getDevice()); + options.put(GPSSerialDevice.PORT_SPEED_KEY, getConfig().getSpeed()); + + if (logger.isDebugEnabled()) { + logger.debug("GPS options: " + options); + } + + gpsDevice.init(options); + gpsDataProcessor.setGPSDevice(gpsDevice); + + deviceInitialized = true; } - gpsDevice.init(options); - gpsDataProcessor.setGPSDevice(gpsDevice); + if (logger.isTraceEnabled()) { + Enumeration portList = CommPortIdentifier.getPortIdentifiers(); - } catch (GPSException ex) { - throw new SammoaTechnicalException("Can't connect to gps", ex); - } + while (portList.hasMoreElements()) { + CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement(); + if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { + logger.trace("Available SERIAL port : " + portId.getName()); + } + } + } - // try to reconnect - try { gpsDataProcessor.open(); + + gpsDataProcessor.addGPSDataChangeListener( + GPSDataProcessor.LOCATION, gpsDataProcessorListener); + gpsDataProcessor.addGPSDataChangeListener( + GPSDataProcessor.ALTITUDE, gpsDataProcessorListener); + gpsDataProcessor.addGPSDataChangeListener( + GPSDataProcessor.SPEED, gpsDataProcessorListener); + logger.info("Connected to GPS device"); + + setState(DeviceState.READY); + } catch (GPSException ex) { - logger.trace("Can't connect to gps device"); + + setState(DeviceState.NO_DEVICE); + + throw new DeviceTechnicalException(this, "Can't open GPS device", ex); } } + @Override + public void close() { + + stop(); + + if (gpsDataProcessor != null && getState() != DeviceState.NO_DEVICE) { + + logger.info("Closing GPS device..."); + try { + + gpsDataProcessor.removeGPSDataChangeListener( + GPSDataProcessor.LOCATION, gpsDataProcessorListener); + gpsDataProcessor.removeGPSDataChangeListener( + GPSDataProcessor.ALTITUDE, gpsDataProcessorListener); + gpsDataProcessor.removeGPSDataChangeListener( + GPSDataProcessor.SPEED, gpsDataProcessorListener); + + gpsDataProcessor.close(); + + logger.info("GPS device is closed"); + + setState(DeviceState.NO_DEVICE); + + } catch (GPSException e) { + throw new DeviceTechnicalException(this, "Can't close GPS device", e); + } + } + } + + @Override + public GeoPoint getCurrentLocation() { + + GeoPoint result = null; + + logger.trace("Ask lastPosition = {}", lastPosition); + + if (!Objects.equal(lastPosition, lastSendPosition) && lastPosition != null) { + + result = new GeoPointImpl(lastPosition.getLatitude(), lastPosition.getLongitude()); + result.setAltitude(lastAltitude); + result.setSpeed(lastSpeed); + // FIXME-fdesbois-2012-07-02 : ensure time with GPS value and not system timestamp + result.setRecordTime(new Date()); + + lastSendPosition = lastPosition; + } + return result; + } + + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); + } + /** * Si l'on recoit des evenements, c'est que le gps fonctionne. * Il sont envoyé par le traitement des flux NMEA et propagé par le @@ -138,54 +213,24 @@ * <li>VDOP: a Float indicating the quality of the gps signal in vertical direction. * </ul> */ - @Override - public void propertyChange(PropertyChangeEvent evt) { + protected PropertyChangeListener gpsDataProcessorListener = new PropertyChangeListener() { - String property = evt.getPropertyName(); + @Override + public void propertyChange(PropertyChangeEvent evt) { - if (trackingStarted) { + String property = evt.getPropertyName(); logger.trace("Gps data received {} {}", property, evt.getNewValue()); - // update timestamp of the last notification - lastDataReceivedTimeStamp = System.currentTimeMillis(); - if (GPSDataProcessor.LOCATION.equals(property)) { lastPosition = (GPSPosition) evt.getNewValue(); + } else if (GPSDataProcessor.ALTITUDE.equals(property)) { lastAltitude = (Float) evt.getNewValue(); + } else if (GPSDataProcessor.SPEED.equals(property)) { lastSpeed = (Float) evt.getNewValue(); } } - } - - @Override - public GeoPoint getCurrentLocation() { - - logger.trace("Ask for position = {}", lastPosition); - - GeoPoint location = null; - if (!Objects.equal(lastPosition, lastSendPosition) && lastPosition != null) { - - location = new GeoPointImpl(lastPosition.getLatitude(), lastPosition.getLongitude()); - location.setAltitude(lastAltitude); - location.setSpeed(lastSpeed); - // FIXME-fdesbois-2012-07-02 : ensure time with GPS value and not system timestamp - location.setRecordTime(new Date()); - - lastSendPosition = lastPosition; - } - - return location; - } - - @Override - protected void finalize() throws Throwable { - if (gpsDataProcessor != null) { - logger.info("Closing GPS device"); - gpsDataProcessor.close(); - } - super.finalize(); - } + }; } Modified: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsUpdateListener.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsUpdateListener.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/GpsUpdateListener.java 2012-08-06 14:33:43 UTC (rev 357) @@ -24,25 +24,19 @@ */ package fr.ulr.sammoa.application.gps; -import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceUpdateEvent; +import fr.ulr.sammoa.application.DeviceUpdateListener; import fr.ulr.sammoa.persistence.GeoPoint; /** * DP Observateur. */ -public interface GpsUpdateListener { +public interface GpsUpdateListener extends DeviceUpdateListener { /** * Update GPS location. * - * @param newLocation new location + * @param event new event */ - void onLocationReceived(GeoPoint newLocation); - - /** - * Update GPS state. - * - * @param state new state - */ - void onStateChanged(DeviceState state); + void onLocationReceived(DeviceUpdateEvent<GeoPoint> event); } Added: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/SammoaGPSSerialDevice.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/SammoaGPSSerialDevice.java (rev 0) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/SammoaGPSSerialDevice.java 2012-08-06 14:33:43 UTC (rev 357) @@ -0,0 +1,67 @@ +package fr.ulr.sammoa.application.gps; +/* + * #%L + * SAMMOA :: Application + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2012 UMS 3462, Code Lutin + * %% + * This program 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. + * + * This program 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 this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import gnu.io.RXTXHack; +import gnu.io.RXTXPort; +import org.dinopolis.gpstool.gpsinput.GPSException; +import org.dinopolis.gpstool.gpsinput.GPSSerialDevice; + +/** + * There is an issue with closing on {@link gnu.io.SerialPort}. See + * <a href="https://forums.oracle.com/forums/thread.jspa?threadID=1292323"> + * https://forums.oracle.com/forums/thread.jspa?threadID=1292323 + * </a> + * + * Note that only the {@link RXTXHack} works... Maybe the upgrade of rxtx.jar could + * works (not in maven repo). + * <p/> + * The issue is probably from {@link org.dinopolis.gpstool.gpsinput.nmea.GPSNmeaDataProcessor} + * that creates a daemon thread to read the serialPort InputStream. There is + * no way to kill properly this thread before closing serialPort. + * + * Created: 06/08/12 + * + * @author fdesbois <florian.desbois@codelutin.com> + */ +public class SammoaGPSSerialDevice extends GPSSerialDevice { + + @Override + public void close() throws GPSException { + if (serial_port_ != null) { + +// serial_port_.removeEventListener(); +// try { +// serial_port_.getOutputStream().flush(); +// serial_port_.getOutputStream().close(); +// serial_port_.getInputStream().close(); +// } catch (IOException e) { +// throw Throwables.propagate(e); +// } +// serial_port_.close(); + + RXTXHack.closeRxtxPort((RXTXPort) serial_port_); + } + } +} Property changes on: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/gps/SammoaGPSSerialDevice.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/sammoa-application/src/main/java/gnu/io/RXTXHack.java (from rev 356, trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/audio/AudioUpdateListener.java) =================================================================== --- trunk/sammoa-application/src/main/java/gnu/io/RXTXHack.java (rev 0) +++ trunk/sammoa-application/src/main/java/gnu/io/RXTXHack.java 2012-08-06 14:33:43 UTC (rev 357) @@ -0,0 +1,42 @@ +package gnu.io; +/* + * #%L + * SAMMOA :: Application + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2012 UMS 3462, Code Lutin + * %% + * This program 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. + * + * This program 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 this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +/** + * Created: 06/08/12 + * + * @author fdesbois <florian.desbois@codelutin.com> + * @see fr.ulr.sammoa.application.gps.SammoaGPSSerialDevice for usage + */ +public final class RXTXHack { + + private RXTXHack() { + // final class with static methods + } + + public static void closeRxtxPort(RXTXPort port) { + port.IOLocked = 0; + port.close(); + } +} Property changes on: trunk/sammoa-application/src/main/java/gnu/io/RXTXHack.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/MainUIHandler.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/MainUIHandler.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/MainUIHandler.java 2012-08-06 14:33:43 UTC (rev 357) @@ -24,6 +24,7 @@ */ package fr.ulr.sammoa.ui.swing; +import fr.ulr.sammoa.application.DeviceTechnicalException; import fr.ulr.sammoa.application.FlightState; import fr.ulr.sammoa.application.SammoaConfig; import fr.ulr.sammoa.application.SammoaContext; @@ -35,6 +36,7 @@ import fr.ulr.sammoa.ui.swing.flight.FlightUIHandler; import fr.ulr.sammoa.ui.swing.home.HomeUI; import fr.ulr.sammoa.ui.swing.io.exportMap.ExportMapUI; +import fr.ulr.sammoa.ui.swing.util.SammoaUtil; import jaxx.runtime.SwingUtil; import jaxx.runtime.swing.AboutPanel; import jaxx.runtime.swing.ErrorDialogUI; @@ -90,10 +92,10 @@ @Override public void afterInitUI() { - // 3- Synch to error dialog + // Sync to error dialog ErrorDialogUI.init(ui); - // 4- Init SwingSession + // Init SwingSession SwingSession swingSession = new SwingSession(getConfig().getUIConfigFile(), false); swingSession.add(ui); swingSession.save(); @@ -295,7 +297,12 @@ FlightUIHandler flightUIHandler = context.getFlightUIHandler(); if (flightUIHandler != null) { GpsConfig gpsConfig = context.getConfig().getGpsConfig(); - flightUIHandler.getFlightController().initGpsHandler(gpsConfig); + try { + flightUIHandler.getFlightController().openGpsDevice(gpsConfig); + } catch (DeviceTechnicalException ex) { + logger.error("Error on new GpsHandler", ex); + SammoaUtil.showError(ui, ex); + } } } }); Deleted: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/AudioStateLED.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/AudioStateLED.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/AudioStateLED.java 2012-08-06 14:33:43 UTC (rev 357) @@ -1,48 +0,0 @@ -/* - * #%L - * SAMMOA :: UI Swing - * - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2012 UMS 3462, Code Lutin - * %% - * This program 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. - * - * This program 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 this program. If not, see - * <http://www.gnu.org/licenses/gpl-3.0.html>. - * #L% - */ - -package fr.ulr.sammoa.ui.swing.flight; - -import fr.ulr.sammoa.application.audio.AudioUpdateListener; - -/** - * Panel qui écoute l'état du gps pour afficher à l'utilsateur un voyant - * lunineux dépendant de l'état du peripherique audio. - * - * Indicateurs pour l'état du GPS - * <ul> - * <li>voyant gris : pas de peripherique - * <li>voyant bleu : peripherique prêt - * <li>voyant vert : enregistrement en cours - * <li>voyant rouge clignotant : enregistrement mais pas de données - * </ul> - * - * @author echatellier - */ -public class AudioStateLED extends DeviceStateLED implements AudioUpdateListener { - - /** serialVersionUID. */ - private static final long serialVersionUID = 1L; -} Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/DeviceStateLED.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/DeviceStateLED.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/DeviceStateLED.java 2012-08-06 14:33:43 UTC (rev 357) @@ -25,29 +25,41 @@ package fr.ulr.sammoa.ui.swing.flight; import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceUpdateEvent; +import fr.ulr.sammoa.application.DeviceUpdateListener; +import fr.ulr.sammoa.application.gps.GpsUpdateListener; +import fr.ulr.sammoa.persistence.GeoPoint; import org.nuiton.util.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.swing.ImageIcon; -import javax.swing.JLabel; +import javax.swing.*; /** - * Classe abtraite permettant d'obtenir et d'afficher l'état d'un périphérique. + * Panel qui écoute l'état du peripherique pour afficher à l'utilsateur un voyant + * lunineux dépendant de l'état du peripherique. + * + * Indicateurs pour l'état du peripherique + * <ul> + * <li>voyant gris : pas de peripherique + * <li>voyant bleu : peripherique prêt + * <li>voyant vert : enregistrement en cours + * <li>voyant rouge clignotant : enregistrement mais pas de données + * </ul> * * @author chatellier */ -public abstract class DeviceStateLED extends JLabel { +public class DeviceStateLED extends JLabel implements DeviceUpdateListener, GpsUpdateListener { - private static final Logger logger = LoggerFactory.getLogger(DeviceStateLED.class); - /** serialVersionUID. */ private static final long serialVersionUID = 1L; + private static final Logger logger = LoggerFactory.getLogger(DeviceStateLED.class); + protected DeviceState state; public DeviceStateLED() { - onStateChanged(DeviceState.NO_DEVICE); +// onStateChanged(DeviceState.NO_DEVICE); } protected static final ImageIcon NO_DEVICE_ICON = Resource.getIcon("/icons/device/nodevice.png"); @@ -55,9 +67,10 @@ protected static final ImageIcon RECORDING_ICON = Resource.getIcon("/icons/device/recording.png"); protected static final ImageIcon NO_DATA_ICON = Resource.getIcon("/icons/device/nodata.gif"); - public void onStateChanged(DeviceState state) { + @Override + public void onStateChanged(DeviceUpdateEvent<DeviceState> event) { DeviceState oldValue = getState(); - this.state = state; + this.state = event.getNewValue(); if (oldValue != state) { @@ -84,4 +97,9 @@ public DeviceState getState() { return state; } + + @Override + public void onLocationReceived(DeviceUpdateEvent<GeoPoint> event) { + // nothing to do + } } Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBar.jaxx =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBar.jaxx 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBar.jaxx 2012-08-06 14:33:43 UTC (rev 357) @@ -85,8 +85,8 @@ </cell> <cell fill='horizontal' weightx='0.2' anchor='center'> <JPanel id='cbPanel' layout='{new BoxLayout(cbPanel, BoxLayout.Y_AXIS)}'> - <GpsStateLED id='gpsLED' /> - <AudioStateLED id='audioLED' /> + <DeviceStateLED id='gpsLED' /> + <DeviceStateLED id='audioLED' /> </JPanel> </cell> <cell fill='vertical'> Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBarHandler.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBarHandler.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBarHandler.java 2012-08-06 14:33:43 UTC (rev 357) @@ -51,19 +51,11 @@ return view.getModel(); } - public AudioStateLED getAudioLED() { - return view.getAudioLED(); - } - - public GpsStateLED getGpsLED() { - return view.getGpsLED(); - } - public void init() { getFlightUIModel().addPropertyChangeListener(this); - getFlightController().getAudioRecorder().addAudioUpdateListener(getAudioLED()); - getFlightController().getGpsHandler().addGpsUpdateListener(getGpsLED()); - getFlightController().getGpsHandler().addGpsUpdateListener(getModel()); + getFlightController().getAudioRecorder().addUpdateListener(view.getAudioLED()); + getFlightController().getGpsHandler().addUpdateListener(view.getGpsLED()); + getFlightController().getGpsHandler().addUpdateListener(getModel()); } @Override Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBarModel.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBarModel.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightBarModel.java 2012-08-06 14:33:43 UTC (rev 357) @@ -25,11 +25,12 @@ package fr.ulr.sammoa.ui.swing.flight; import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceUpdateEvent; import fr.ulr.sammoa.application.gps.GpsUpdateListener; import fr.ulr.sammoa.persistence.GeoPoint; import fr.ulr.sammoa.ui.swing.BaseModel; -import java.awt.Color; +import java.awt.*; import static org.nuiton.i18n.I18n._; @@ -81,7 +82,8 @@ } @Override - public void onLocationReceived(GeoPoint newLocation) { + public void onLocationReceived(DeviceUpdateEvent<GeoPoint> event) { + GeoPoint newLocation = event.getNewValue(); if (newLocation != null) { setSpeed((float) newLocation.getSpeed()); setAlt((float) newLocation.getAltitude()); @@ -89,7 +91,7 @@ } @Override - public void onStateChanged(DeviceState state) { + public void onStateChanged(DeviceUpdateEvent<DeviceState> event) { // nothing to do } } Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightUIHandler.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightUIHandler.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/FlightUIHandler.java 2012-08-06 14:33:43 UTC (rev 357) @@ -47,6 +47,8 @@ import com.google.common.collect.Maps; import com.google.common.collect.Ordering; import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceTechnicalException; +import fr.ulr.sammoa.application.DeviceUpdateEvent; import fr.ulr.sammoa.application.FlightController; import fr.ulr.sammoa.application.FlightControllerDefault; import fr.ulr.sammoa.application.FlightControllerUpdateListener; @@ -84,6 +86,7 @@ import fr.ulr.sammoa.ui.swing.flight.layer.StrateLayer; import fr.ulr.sammoa.ui.swing.flight.layer.TransectLayer; import fr.ulr.sammoa.ui.swing.transect.TransectUI; +import fr.ulr.sammoa.ui.swing.util.SammoaUtil; import jaxx.runtime.JAXXObject; import jaxx.runtime.SwingUtil; import org.nuiton.util.ApplicationConfig; @@ -143,6 +146,10 @@ return context.getAppContext(); } + public FlightUI getUI() { + return ui; + } + public FlightController getFlightController() { return flightController; } @@ -203,7 +210,23 @@ startTime = timeLog.log(startTime, "beforeInitUI", "entities are loaded"); flightController = new FlightControllerDefault(getAppContext(), flight); + + try { + flightController.openGpsDevice(getConfig().getGpsConfig()); + } catch (DeviceTechnicalException ex) { + logger.error("Error on FlightController init", ex); + SammoaUtil.showError(ui, ex); + } + + try { + flightController.openAudioDevice(); + } catch (DeviceTechnicalException ex) { + logger.error("Error on FlightController init", ex); + SammoaUtil.showError(ui, ex); + } + flightController.addListener(this); + flightController.init(); FlightUIModel model = new FlightUIModel(); @@ -358,20 +381,21 @@ initMapHandler(); - getFlightController().getGpsHandler().addGpsUpdateListener( + getFlightController().getGpsHandler().addUpdateListener( new GpsUpdateListener() { @Override - public void onLocationReceived(GeoPoint newLocation) { + public void onLocationReceived(DeviceUpdateEvent<GeoPoint> event) { + GeoPoint newLocation = event.getNewValue(); if (newLocation != null && getModel().isMapFollow()) { MapBean mapBean = getOverlayMapPanel().getMapBean(); mapBean.setCenter(new LatLonPoint.Double(newLocation.getLatitude(), - newLocation.getLongitude())); + newLocation.getLongitude())); } } @Override - public void onStateChanged(DeviceState state) { + public void onStateChanged(DeviceUpdateEvent<DeviceState> event) { // nothing to do } }); @@ -725,7 +749,7 @@ // Ajout d'un layer pour représenter les points relevés par le GPS GpsTracingLayer gpsTracingLayer = new GpsTracingLayer(); - getFlightController().getGpsHandler().addGpsUpdateListener(gpsTracingLayer); + getFlightController().getGpsHandler().addUpdateListener(gpsTracingLayer); mapHandler.add(gpsTracingLayer); InformationDelegator informationDelegator = new InformationDelegator(); Deleted: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/GpsStateLED.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/GpsStateLED.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/GpsStateLED.java 2012-08-06 14:33:43 UTC (rev 357) @@ -1,58 +0,0 @@ -/* - * #%L - * SAMMOA :: UI Swing - * - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2012 UMS 3462, Code Lutin - * %% - * This program 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. - * - * This program 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 this program. If not, see - * <http://www.gnu.org/licenses/gpl-3.0.html>. - * #L% - */ - -package fr.ulr.sammoa.ui.swing.flight; - -import fr.ulr.sammoa.application.gps.GpsUpdateListener; -import fr.ulr.sammoa.persistence.GeoPoint; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Panel qui écoute l'état du gps pour afficher à l'utilsateur un voyant - * lunineux dépendant de l'état du gps. - * - * Indicateurs pour l'état du GPS - * <ul> - * <li>voyant gris : pas de GPS - * <li>voyant bleu : GPS prêt - * <li>voyant vert : enregistrement en cours - * <li>voyant rouge clignotant : enregistrement mais pas de données GPS - * </ul> - * - * @author echatellier - */ -public class GpsStateLED extends DeviceStateLED implements GpsUpdateListener { - - private static final Logger logger = LoggerFactory.getLogger(GpsStateLED.class); - - /** serialVersionUID. */ - private static final long serialVersionUID = 1L; - - @Override - public void onLocationReceived(GeoPoint newLocation) { - // nothing to do - } -} Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/layer/GpsTracingLayer.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/layer/GpsTracingLayer.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/flight/layer/GpsTracingLayer.java 2012-08-06 14:33:43 UTC (rev 357) @@ -30,6 +30,7 @@ import com.bbn.openmap.omGraphics.OMGraphicList; import com.bbn.openmap.omGraphics.OMLine; import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceUpdateEvent; import fr.ulr.sammoa.application.gps.GpsUpdateListener; import fr.ulr.sammoa.persistence.GeoPoint; import fr.ulr.sammoa.persistence.GeoPointImpl; @@ -51,9 +52,11 @@ } @Override - public void onLocationReceived(GeoPoint newLocation) { + public void onLocationReceived(DeviceUpdateEvent<GeoPoint> event) { // OMGraphic point = new OMPoint(newLocation.getLatitude(), newLocation.getLongitude()); + GeoPoint newLocation = event.getNewValue(); + if (currentLocation == null) { // do not display the first location point @@ -87,7 +90,7 @@ } @Override - public void onStateChanged(DeviceState state) { - + public void onStateChanged(DeviceUpdateEvent<DeviceState> event) { + // nothing to do } } Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/EffortPanelHandler.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/EffortPanelHandler.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/observations/EffortPanelHandler.java 2012-08-06 14:33:43 UTC (rev 357) @@ -24,9 +24,10 @@ */ import fr.ulr.sammoa.application.DeviceState; +import fr.ulr.sammoa.application.DeviceUpdateEvent; +import fr.ulr.sammoa.application.DeviceUpdateListener; import fr.ulr.sammoa.application.FlightController; import fr.ulr.sammoa.application.FlightService; -import fr.ulr.sammoa.application.audio.AudioUpdateListener; import fr.ulr.sammoa.application.gps.GpsUpdateListener; import fr.ulr.sammoa.persistence.GeoPoint; import fr.ulr.sammoa.persistence.Observation; @@ -96,7 +97,7 @@ * @author tchemit <chemit@codelutin.com> * @since 0.4 */ -public class EffortPanelHandler implements GpsUpdateListener, AudioUpdateListener { +public class EffortPanelHandler implements DeviceUpdateListener, GpsUpdateListener { private static final Logger logger = LoggerFactory.getLogger(EffortPanelHandler.class); @@ -274,8 +275,8 @@ SammoaUIContext.getUIContext().getFlightUIHandler().getFlightController(); if (flightController != null) { - flightController.getGpsHandler().addGpsUpdateListener(this); - flightController.getAudioRecorder().addAudioUpdateListener(this); + flightController.getGpsHandler().addUpdateListener(this); + flightController.getAudioRecorder().addUpdateListener(this); } @@ -551,12 +552,8 @@ } @Override - public void onLocationReceived(GeoPoint newLocation) { - // do nothing - } - - @Override - public void onStateChanged(DeviceState state) { + public void onStateChanged(DeviceUpdateEvent<DeviceState> event) { + DeviceState state = event.getNewValue(); if (DeviceState.NO_DATA == state) { ui.getObservationTable().setBackground(DEVICE_ERROR_BACKGROUND_COLOR); @@ -565,11 +562,15 @@ } } + @Override + public void onLocationReceived(DeviceUpdateEvent<GeoPoint> event) { + // nothing to do + } + public DecoratorProvider getDecoratorProvider() { return SammoaUIContext.getUIContext().getDecoratorProvider(); } - public static void init(final JXTable table, ListSelectionListener selectionListener) { Modified: trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/util/SammoaUtil.java =================================================================== --- trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/util/SammoaUtil.java 2012-08-06 12:52:57 UTC (rev 356) +++ trunk/sammoa-ui-swing/src/main/java/fr/ulr/sammoa/ui/swing/util/SammoaUtil.java 2012-08-06 14:33:43 UTC (rev 357) @@ -26,6 +26,7 @@ import com.google.common.base.Joiner; import com.google.common.base.Throwables; +import fr.ulr.sammoa.application.DeviceTechnicalException; import jaxx.runtime.JAXXUtil; import jaxx.runtime.SwingUtil; import org.apache.commons.beanutils.NestedNullException; @@ -36,12 +37,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.swing.Action; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JRootPane; -import javax.swing.KeyStroke; +import javax.swing.*; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; @@ -230,4 +226,18 @@ ui.setCursor(Cursor.getDefaultCursor()); } } + + public static void showError(Component ui, DeviceTechnicalException ex) { + String message = ex.getMessage(); + if (ex.getCause() != null) { + message += " : " + ex.getCause().getMessage(); + } + JOptionPane.showMessageDialog( + ui, + message, + "Error", + JOptionPane.ERROR_MESSAGE, + UIManager.getIcon("error") + ); + } }
participants (1)
-
fdesbois@users.forge.codelutin.com