From 1d7ba9c4d4389b736f13aedffe053b21a70e0fe2 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 15 Apr 2024 11:14:51 +0100 Subject: [PATCH 01/92] comm/manager/imc/ImcMsgManager: Some refactor. --- .../comm/manager/imc/ImcMsgManager.java | 608 +----------------- .../imc/ImcMsgManagerAnnounceProcessor.java | 352 ++++++++++ .../imc/ImcMsgManagerMessageProcessor.java | 346 ++++++++++ 3 files changed, 718 insertions(+), 588 deletions(-) create mode 100644 src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java create mode 100644 src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java index 3a04da2c66..ded2103b95 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java @@ -127,7 +127,7 @@ public class ImcMsgManager extends public static final String TRANSPORT_UDP = "UDP"; public static final String TRANSPORT_TCP = "TCP"; - private static final int DEFAULT_UDP_VEH_PORT = 6002; + static final int DEFAULT_UDP_VEH_PORT = 6002; /** * Singleton @@ -138,8 +138,6 @@ public class ImcMsgManager extends private boolean sameIdErrorDetected = false; private long sameIdErrorDetectedTimeMillis = -1; - protected IMCFragmentHandler fragmentHandler;; - protected ImcSystemState imcState; // public static String CCU_VEH_STRING = "CCU-VEH"; @@ -156,15 +154,18 @@ public class ImcMsgManager extends private boolean logSentMsg = false; @Deprecated - private boolean dontIgnoreIpSourceRequest = true; + boolean dontIgnoreIpSourceRequest = true; private boolean multicastEnabled = true; private String multicastAddress = "224.0.75.69"; private int[] multicastPorts = new int[] { 6969 }; private boolean broadcastEnabled = true; - private final IMCDefinition imcDefinition; // = IMCDefinition.getInstance(); - private AnnounceWorker announceWorker; // = new AnnounceWorker(this, imcDefinition); + private ImcMsgManagerAnnounceProcessor announceProcessor; + private ImcMsgManagerMessageProcessor messageProcessor; + + final IMCDefinition imcDefinition; // = IMCDefinition.getInstance(); + AnnounceWorker announceWorker; // = new AnnounceWorker(this, imcDefinition); private long announceLastArriveTime = -1; private final PreferencesListener gplistener; @@ -280,10 +281,12 @@ public void preferencesUpdated() { this.imcDefinition = imcDefinition; announceWorker = new AnnounceWorker(this, imcDefinition); - fragmentHandler = new IMCFragmentHandler(imcDefinition); imcState = new ImcSystemState(imcDefinition); imcState.setIgnoreEntities(true); + announceProcessor = new ImcMsgManagerAnnounceProcessor(this); + messageProcessor = new ImcMsgManagerMessageProcessor(this); + GeneralPreferences.addPreferencesListener(gplistener); gplistener.preferencesUpdated(); } @@ -351,7 +354,7 @@ private void updateUdpOnIpMapper() { } } - private void updateUdpOnIpMapper(SystemImcMsgCommInfo vsci) { + void updateUdpOnIpMapper(SystemImcMsgCommInfo vsci) { if (isUdpOn()) udpOnIpMapper.forcePut(vsci.getIpAddress() + (isFilterByPort ? ":" + vsci.getIpRemotePort() : ""), vsci.getSystemCommId()); @@ -773,283 +776,6 @@ public boolean is2IdErrorMode() { return sameIdErrorDetected; } - private void processEntityInfo(MessageInfo info, EntityInfo msg) { - imcDefinition.getResolver().setEntityName(msg.getSrc(), msg.getSrcEnt(), msg.getLabel()); - } - - private void processMessagePart(MessageInfo info, MessagePart msg) { - IMCMessage m = fragmentHandler.setFragment((MessagePart)msg); - if (m != null) - postInternalMessage(msg.getSourceName(), m); - } - - private void processEntityList(ImcId16 id, MessageInfo info, EntityList msg) { - EntitiesResolver.setEntities(id.toString(), msg); - imcDefinition.getResolver().setEntityMap(msg.getSrc(), msg.getList()); - ImcSystem sys = ImcSystemsHolder.lookupSystem(id); - if (sys != null) { - EntitiesResolver.setEntities(sys.getName(), msg); - } - } - - private void processReportedState(MessageInfo info, ReportedState msg) { - // Process pos. state reported from other system - String sysId = msg.getSid(); - - double latRad = msg.getLat(); - double lonRad = msg.getLon(); - double depth = msg.getDepth(); - - double rollRad = msg.getRoll(); - double pitchRad = msg.getPitch(); - double yawRad = msg.getYaw(); - - double recTimeSecs = msg.getRcpTime(); - long recTimeMillis = Double.isFinite(recTimeSecs) ? (long) (recTimeSecs * 1E3) : msg.getTimestampMillis(); - - // msg.getSType(); // Not used - - ImcSystem imcSys = ImcSystemsHolder.lookupSystemByName(sysId); - ExternalSystem extSys = null; - if (imcSys == null) { - extSys = ExternalSystemsHolder.lookupSystem(sysId); - if (extSys == null) { - extSys = new ExternalSystem(sysId); - ExternalSystemsHolder.registerSystem(extSys); - } - } - - if (Double.isFinite(latRad) && Double.isFinite(lonRad)) { - LocationType loc = new LocationType(Math.toDegrees(latRad), Math.toDegrees(lonRad)); - if (Double.isFinite(depth)) - loc.setDepth(depth); - - if (imcSys != null) - imcSys.setLocation(loc, recTimeMillis); - else - extSys.setLocation(loc, recTimeMillis); - } - - if (Double.isFinite(rollRad) || Double.isFinite(pitchRad) || Double.isFinite(yawRad)) { - double rollDeg = Double.isFinite(rollRad) ? Math.toDegrees(rollRad) : 0; - double pitchDeg = Double.isFinite(pitchRad) ? Math.toDegrees(pitchRad) : 0; - double yawDeg = Double.isFinite(yawRad) ? Math.toDegrees(yawRad) : 0; - - if (imcSys != null) - imcSys.setAttitudeDegrees(rollDeg, pitchDeg, yawDeg, recTimeMillis); - else - extSys.setAttitudeDegrees(rollDeg, pitchDeg, yawDeg, recTimeMillis); - } - } - - private void processStateReport(MessageInfo info, StateReport msg, ArrayList messagesCreatedToFoward) { - - String sysId = msg.getSourceName(); - - long dataTimeMillis = msg.getStime() * 1000; - - double lat = msg.getLatitude(); - double lon = msg.getLongitude(); - double depth = msg.getDepth() == 0xFFFF ? -1 : msg.getDepth() / 10.0; - // double altitude = msg.getAltitude() == 0xFFFF ? -1 : msg.getAltitude() / 10.0; - double heading = ((double)msg.getHeading() / 65535.0) * 360; - double speedMS = msg.getSpeed() / 100.; - NeptusLog.pub().info("Received report from "+msg.getSourceName()); - - ImcSystem imcSys = ImcSystemsHolder.lookupSystemByName(sysId); - if (imcSys == null) { - NeptusLog.pub().error("Could not find system with id "+sysId); - return; - } - - LocationType loc = new LocationType(lat, lon); - loc.setDepth(depth); - imcSys.setLocation(loc, dataTimeMillis); - imcSys.setAttitudeDegrees(heading, dataTimeMillis); - - imcSys.storeData(SystemUtils.GROUND_SPEED_KEY, speedMS, dataTimeMillis, true); - imcSys.storeData(SystemUtils.COURSE_DEGS_KEY, - (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(heading, 0)), - dataTimeMillis, true); - imcSys.storeData( - SystemUtils.HEADING_DEGS_KEY, - (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(heading, 0)), - dataTimeMillis, true); - - int fuelPerc = msg.getFuel(); - if (fuelPerc > 0) { - FuelLevel fuelLevelMsg = new FuelLevel(); - IMCUtils.copyHeader(msg, fuelLevelMsg); - fuelLevelMsg.setTimestampMillis(dataTimeMillis); - fuelLevelMsg.setValue(fuelPerc); - fuelLevelMsg.setConfidence(0); - imcSys.storeData(SystemUtils.FUEL_LEVEL_KEY, fuelLevelMsg, dataTimeMillis, true); - - messagesCreatedToFoward.add(fuelLevelMsg); - } - - int execState = msg.getExecState(); - PlanControlState pcsMsg = new PlanControlState(); - IMCUtils.copyHeader(msg, pcsMsg); - pcsMsg.setTimestampMillis(dataTimeMillis); - switch (execState) { - case -1: - pcsMsg.setState(STATE.READY); - break; - case -3: - pcsMsg.setState(STATE.INITIALIZING); - break; - case -2: - case -4: - pcsMsg.setState(STATE.BLOCKED); - break; - default: - if (execState > 0) - pcsMsg.setState(STATE.EXECUTING); - else - pcsMsg.setState(STATE.BLOCKED); - break; - } - - pcsMsg.setPlanEta(-1); - pcsMsg.setPlanProgress(execState >= 0 ? execState : -1); - pcsMsg.setManId(""); - pcsMsg.setManEta(-1); - pcsMsg.setManType(0xFFFF); - - messagesCreatedToFoward.add(pcsMsg); - } - - private void processAssetReport(MessageInfo info, AssetReport msg, ArrayList messagesCreatedToFoward) { - - String reporterId = msg.getSourceName(); - String sysId = msg.getName(); - - long dataTimeMillis = Double.valueOf(msg.getReportTime() * 1000).longValue(); - - AssetReport.MEDIUM mediumReported = msg.getMedium(); - - double latRad = msg.getLat(); - double lonRad = msg.getLon(); - double depth = msg.getDepth(); - double altitude = msg.getAlt(); - - double speedMS = msg.getSog(); - double cogRads = msg.getCog(); - - ArrayList otherMsgs = Collections.list(msg.getMsgs().elements()); // TODO - - ImcSystem imcSys = ImcSystemsHolder.lookupSystemByName(sysId); - ExternalSystem extSys = null; - if (imcSys == null) { - extSys = ExternalSystemsHolder.lookupSystem(sysId); - if (extSys == null) { - extSys = new ExternalSystem(sysId); - ExternalSystemsHolder.registerSystem(extSys); - } - } - - if (Double.isFinite(latRad) && Double.isFinite(lonRad)) { - LocationType loc = new LocationType(AngleUtils.nomalizeAngleDegrees180(Math.toDegrees(latRad)), - AngleUtils.nomalizeAngleDegrees180(Math.toDegrees(lonRad))); - if (Double.isFinite(depth)) { - loc.setDepth(depth); - } - if (imcSys != null) { - imcSys.setLocation(loc, dataTimeMillis); - } else { - extSys.setLocation(loc, dataTimeMillis); - } - } - double headingRads = Double.NaN; - if (Double.isFinite(cogRads) && Double.isFinite(speedMS) && Math.abs(speedMS) > 0.2) { - headingRads = AngleUtils.nomalizeAngleRads2Pi(cogRads * (speedMS < 0 ? -1 : 1)); - if (imcSys != null) { - imcSys.setAttitudeDegrees(headingRads, dataTimeMillis); - imcSys.storeData( - SystemUtils.HEADING_DEGS_KEY, - (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(Math.toDegrees(headingRads), 0)), - dataTimeMillis, true); - } else { - extSys.setAttitudeDegrees(headingRads, dataTimeMillis); - extSys.storeData( - SystemUtils.HEADING_DEGS_KEY, - (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(Math.toDegrees(headingRads), 0)), - dataTimeMillis, true); - } - } - - if (imcSys != null) { - imcSys.storeData(SystemUtils.GROUND_SPEED_KEY, speedMS, dataTimeMillis, true); - imcSys.storeData(SystemUtils.COURSE_DEGS_KEY, - (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(Math.toDegrees(cogRads), 0)), - dataTimeMillis, true); - } else { - extSys.storeData(SystemUtils.GROUND_SPEED_KEY, speedMS, dataTimeMillis, true); - extSys.storeData(SystemUtils.COURSE_DEGS_KEY, - (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(Math.toDegrees(cogRads), 0)), - dataTimeMillis, true); - } - } - - private void processRemoteSensorInfo(MessageInfo info, RemoteSensorInfo msg) { - // Process pos. state reported from other system - String sysId = msg.getId(); - - double latRad = msg.getLat(); - double lonRad = msg.getLon(); - double altitude = msg.getAlt(); - - double headingRad = msg.getHeading(); - - String sensorClass = msg.getSensorClass(); - - long recTimeMillis = msg.getTimestampMillis(); - - ImcSystem imcSys = ImcSystemsHolder.lookupSystemByName(sysId); - ExternalSystem extSys = null; - if (imcSys == null) { - extSys = ExternalSystemsHolder.lookupSystem(sysId); - if (extSys == null) { - extSys = new ExternalSystem(sysId); - ExternalSystemsHolder.registerSystem(extSys); - } - } - - if (Double.isFinite(latRad) && Double.isFinite(lonRad)) { - LocationType loc = new LocationType(Math.toDegrees(latRad), Math.toDegrees(lonRad)); - if (Double.isFinite(altitude)) - loc.setDepth(-altitude); - - if (imcSys != null) - imcSys.setLocation(loc, recTimeMillis); - else - extSys.setLocation(loc, recTimeMillis); - } - - if (Double.isFinite(headingRad)) { - double headingDeg = Math.toDegrees(headingRad); - - if (imcSys != null) - imcSys.setAttitudeDegrees(headingDeg, recTimeMillis); - else - extSys.setAttitudeDegrees(headingDeg, recTimeMillis); - } - - // Process sensor class - SystemTypeEnum type = SystemUtils.getSystemTypeFrom(sensorClass); - VehicleTypeEnum typeVehicle = SystemUtils.getVehicleTypeFrom(sensorClass); - ExternalTypeEnum typeExternal = SystemUtils.getExternalTypeFrom(sensorClass); - if (imcSys != null) { - imcSys.setType(type); - imcSys.setTypeVehicle(typeVehicle); - } - else { - extSys.setType(type); - extSys.setTypeVehicle(typeVehicle); - extSys.setTypeExternal(typeExternal); - } - } @Override protected boolean processMsgLocally(MessageInfo info, IMCMessage msg) { @@ -1105,28 +831,28 @@ protected boolean processMsgLocally(MessageInfo info, IMCMessage msg) { switch (msg.getMgid()) { case Announce.ID_STATIC: announceLastArriveTime = System.currentTimeMillis(); - vci = processAnnounceMessage(info, (Announce) msg, vci, id); + vci = announceProcessor.processAnnounceMessage(info, (Announce) msg, vci, id); break; case EntityList.ID_STATIC: - processEntityList(id, info, (EntityList) msg); + messageProcessor.processEntityList(id, info, (EntityList) msg); break; case EntityInfo.ID_STATIC: - processEntityInfo(info, (EntityInfo) msg); + messageProcessor.processEntityInfo(info, (EntityInfo) msg); break; case MessagePart.ID_STATIC: - processMessagePart(info, (MessagePart) msg); + messageProcessor.processMessagePart(info, (MessagePart) msg); break; case ReportedState.ID_STATIC: - processReportedState(info, (ReportedState) msg); + messageProcessor.processReportedState(info, (ReportedState) msg); break; case RemoteSensorInfo.ID_STATIC: - processRemoteSensorInfo(info, (RemoteSensorInfo) msg); + messageProcessor.processRemoteSensorInfo(info, (RemoteSensorInfo) msg); break; case StateReport.ID_STATIC: - processStateReport(info, new StateReport(msg), messagesCreatedToFoward); + messageProcessor.processStateReport(info, new StateReport(msg), messagesCreatedToFoward); break; case AssetReport.ID_STATIC: - processAssetReport(info, new AssetReport(msg), messagesCreatedToFoward); + messageProcessor.processAssetReport(info, new AssetReport(msg), messagesCreatedToFoward); break; default: break; @@ -1238,300 +964,6 @@ private void postToBus(IMCMessage msg) { } } - /** - * @param info - * @param msg - * @param vci - * @param id - * @return - * @throws IOException - */ - private SystemImcMsgCommInfo processAnnounceMessage(MessageInfo info, Announce ann, SystemImcMsgCommInfo vci, - ImcId16 id) throws IOException { - - LocalTime timeStart = LocalTime.now(); - - String sia = info.getPublisherInetAddress(); - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: publisher host address " + sia); - - boolean hostWasGuessed = true; - - InetSocketAddress[] retId = announceWorker.getImcIpsPortsFromMessageImcUdp(ann); - int portUdp = 0; - String hostUdp = ""; - boolean udpIpPortFound = false; - if (retId.length > 0) { - portUdp = retId[0].getPort(); - hostUdp = retId[0].getAddress().getHostAddress(); - } - for (InetSocketAddress add : retId) { - if (sia.equalsIgnoreCase(add.getAddress().getHostAddress())) { - if (ReachableCache.firstReachable(GeneralPreferences.imcReachabilityTestTimeout, add) != null) { - udpIpPortFound = true; - portUdp = add.getPort(); - hostUdp = add.getAddress().getHostAddress(); - hostWasGuessed = false; - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "UDP reachable @ " + hostUdp + ":" + portUdp); - break; - } - } - } - - // Let us try know any one in the announce IPs - if (portUdp > 0 && !udpIpPortFound) { - InetSocketAddress reachableAddr = ReachableCache.firstReachable(GeneralPreferences.imcReachabilityTestTimeout, retId); - if (reachableAddr != null) { - udpIpPortFound = true; - portUdp = reachableAddr.getPort(); - hostUdp = reachableAddr.getAddress().getHostAddress(); - hostWasGuessed = false; - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "UDP reachable @ " + hostUdp + ":" + portUdp); - } - } - - if (portUdp > 0 && !udpIpPortFound) { - // Lets try to see if we received a message from any of the IPs - String ipReceived = hostUdp.isEmpty() ? info.getPublisherInetAddress() : hostUdp; - hostWasGuessed = hostUdp.isEmpty() ? hostWasGuessed : true; - hostUdp = ipReceived; - udpIpPortFound = true; - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "no UDP reachable using " + hostUdp + ":" + portUdp); - } - - InetSocketAddress[] retIdT = announceWorker.getImcIpsPortsFromMessageImcTcp(ann); - int portTcp = 0; - boolean tcpIpPortFound = false; - if (retIdT.length > 0) { - portTcp = retIdT[0].getPort(); - if ("".equalsIgnoreCase(hostUdp)) - hostUdp = retIdT[0].getAddress().getHostAddress(); - } - for (InetSocketAddress add : retIdT) { - if (sia.equalsIgnoreCase(add.getAddress().getHostAddress())) { - if ("".equalsIgnoreCase(hostUdp)) { - if (ReachableCache.firstReachable(GeneralPreferences.imcReachabilityTestTimeout, add) != null) { - tcpIpPortFound = true; - hostUdp = add.getAddress().getHostAddress(); - hostWasGuessed = false; - portTcp = add.getPort(); - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "TCP reachable @ " + hostUdp + ":" + portTcp); - break; - } - else - continue; - } - portTcp = add.getPort(); - tcpIpPortFound = true; - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "no TCP reachable using " + hostUdp + ":" + portTcp); - break; - } - } - - // Let us try know any one in the announce IPs - if (portTcp > 0 && !tcpIpPortFound) { - InetSocketAddress reachableAddr = ReachableCache.firstReachable(GeneralPreferences.imcReachabilityTestTimeout, retId); - if (reachableAddr != null) { - if ("".equalsIgnoreCase(hostUdp)) { - tcpIpPortFound = true; - hostUdp = reachableAddr.getAddress().getHostAddress(); - hostWasGuessed = false; - portTcp = reachableAddr.getPort(); - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "TCP reachable @ " + hostUdp + ":" + portTcp); - } - portTcp = reachableAddr.getPort(); - tcpIpPortFound = true; - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "no TCP reachable using " + hostUdp + ":" + portTcp); - } - } - - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "using UDP@" + hostUdp - + ":" + portUdp + " and using TCP@" + hostUdp + ":" + portTcp + " with host " - + (hostWasGuessed ? "guessed" : "found")); - - boolean requestEntityList = false; - if (vci == null) { - // Create a new system - vci = initSystemCommInfo(id, info.getPublisherInetAddress() + ":" - + (portUdp == 0 ? DEFAULT_UDP_VEH_PORT : portUdp)); - updateUdpOnIpMapper(vci); - requestEntityList = true; - } - // announceWorker.processAnnouceMessage(msg); - String name = ann.getSysName(); - String type = ann.getSysType().toString(); - vci.setSystemIdName(name); - ImcSystem resSys = ImcSystemsHolder.lookupSystem(id); - // NeptusLog.pub().info("<###>......................Announce..." + name + " | " + type + " :: " + hostUdp + " " + - // portUdp); - // NeptusLog.pub().warn(ReflectionUtil.getCallerStamp()+ " ..........................| " + name + " | " + type); - if (resSys != null) { - resSys.setServicesProvided(announceWorker.getImcServicesFromMessage(ann)); - AnnounceWorker.processUidFromServices(resSys); - - // new 2012-06-23 - if (resSys.isOnIdErrorState()) { - EntitiesResolver.clearAliases(resSys.getName()); - EntitiesResolver.clearAliases(resSys.getId()); - } - - resSys.setName(name); - resSys.setType(ImcSystem.translateSystemTypeFromMessage(type)); - resSys.setTypeVehicle(ImcSystem.translateVehicleTypeFromMessage(type)); - // NeptusLog.pub().info(ReflectionUtil.getCallerStamp()+ " ------------------------| " + resSys.getName() + - // " | " + resSys.getType()); - if (portUdp != 0 && udpIpPortFound) { - resSys.setRemoteUDPPort(portUdp); - } - else { - if (resSys.getRemoteUDPPort() == 0) - resSys.setRemoteUDPPort(DEFAULT_UDP_VEH_PORT); - } - if (!"".equalsIgnoreCase(hostUdp) && !AnnounceWorker.NONE_IP.equalsIgnoreCase(hostUdp)) { -// hostWasGuessed = true; - if (AnnounceWorker.USE_REMOTE_IP.equalsIgnoreCase(hostUdp)) { - if (dontIgnoreIpSourceRequest) - resSys.setHostAddress(info.getPublisherInetAddress()); - } - else { - if ((udpIpPortFound || tcpIpPortFound) && !hostWasGuessed) { - resSys.setHostAddress(hostUdp); - } - else if (hostWasGuessed) { - boolean alreadyFound = false; - try { - Map fAddr = new LinkedHashMap<>(); - InetAddress publisherIAddr = InetAddress.getByName(sia); - byte[] pba = publisherIAddr.getAddress(); - int i = 0; - for (InetSocketAddress inetSAddr : retId) { - byte[] lta = inetSAddr.getAddress().getAddress(); - if (lta.length != pba.length) - continue; - i = 0; - for (; i < lta.length; i++) { - if (pba[i] != lta[i]) - break; - } - if (i > 0 && i <= pba.length) - fAddr.put(inetSAddr, i); - } - for (InetSocketAddress inetSAddr : retIdT) { - if (fAddr.containsKey(inetSAddr)) - continue; - byte[] lta = inetSAddr.getAddress().getAddress(); - if (lta.length != pba.length) - continue; - i = 0; - for (; i < lta.length; i++) { - if (pba[i] != lta[i]) - break; - } - if (i > 0 && i <= pba.length) - fAddr.put(inetSAddr, i); - } - - InetSocketAddress foundCandidateAddr = fAddr.keySet().stream().max((a1, a2) -> { - return fAddr.get(a1) - fAddr.get(a2); - }).orElse(null); - if (foundCandidateAddr != null) { - resSys.setHostAddress(foundCandidateAddr.getAddress().getHostAddress()); - alreadyFound = true; - } - } - catch (Exception e) { - e.printStackTrace(); - } - - if (!alreadyFound) { - String curHostAddr = resSys.getHostAddress(); - boolean currIsInAnnounce = false; - for (InetSocketAddress inetSAddr : retId) { - if (curHostAddr.equalsIgnoreCase(inetSAddr.getAddress().getHostAddress())) { - currIsInAnnounce = true; - break; - } - } - if (!currIsInAnnounce) { - for (InetSocketAddress inetSAddr : retIdT) { - if (curHostAddr.equalsIgnoreCase(inetSAddr.getAddress().getHostAddress())) { - currIsInAnnounce = true; - break; - } - } - } - - if (!currIsInAnnounce) - resSys.setHostAddress(hostUdp); - } - } - } - } - if (portTcp != 0 && tcpIpPortFound) { - resSys.setTCPOn(true); - resSys.setRemoteTCPPort(portTcp); - } - else if (portTcp == 0) { - resSys.setTCPOn(false); - } - - if (resSys.isTCPOn() && retId.length == 0) { - resSys.setUDPOn(false); - } - else { - resSys.setUDPOn(true); - } - - NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "final setup UDP@" + resSys.getHostAddress() - + ":" + resSys.getRemoteUDPPort() + " and using TCP@" + resSys.getHostAddress() + ":" + resSys.getRemoteTCPPort()); - - resSys.setOnAnnounceState(true); - - try { - double latRad = ann.getLat(); - double lonRad = ann.getLon(); - double height = ann.getHeight(); - if (latRad != 0 && lonRad != 0) { - LocationType loc = new LocationType(); - loc.setLatitudeDegs(Math.toDegrees(latRad)); - loc.setLongitudeDegs(Math.toDegrees(lonRad)); - loc.setHeight(height); - long locTime = (long) (info.getTimeSentSec() * 1000); - resSys.setLocation(loc, locTime); - } - } - catch (Exception e) { - e.printStackTrace(); - } - - // Adding temp getting heading from services - double headingDegreesFromServices = AnnounceWorker.processHeadingDegreesFromServices(resSys); - if (!Double.isNaN(headingDegreesFromServices) && !Double.isInfinite(headingDegreesFromServices)) { - long attTime = (long) (info.getTimeSentSec() * 1000); - resSys.setAttitudeDegrees(headingDegreesFromServices, attTime); - } - - Map er = EntitiesResolver.getEntities(resSys.getName()); - if (er == null || er.size() == 0) - requestEntityList = true; - - if (requestEntityList) - announceWorker.sendEntityListRequestMsg(resSys); - - ImcSystemsHolder.registerSystem(resSys); - } - - Duration deltaT = Duration.between(timeStart, LocalTime.now()); - if (deltaT.getSeconds() > 1) { - NeptusLog.pub().warn("=====!!===== Too long processing announce DF " + deltaT + " :: " + ann.getAbbrev() + - " @ " + new ImcId16(ann.getSrc()).toPrettyString() + "\n=====!!===== Try reducing " + - "'General Preference->[IMC Communications]-> Reachability Test Timeout' from " + - GeneralPreferences.imcReachabilityTestTimeout + - " to in the order of tens or 1 or 2 hundreds of ms."); - } - - imcDefinition.getResolver().addEntry(ann.getSrc(), ann.getSysName()); - return vci; - } /** * @return the sentMessagesFreqCalc @@ -1750,7 +1182,7 @@ public boolean sendMessage(IMCMessage message, ImcId16 vehicleCommId, String sen * separated string values. Possible values: Multicast and/or Broadcast (if the message is sent by either * or both, it exists), and alternatively UDP or TCP (only if the Multicast and/or Broadcast are not * used). - * @param listener If you want to be warn on the send status of the message. Use null if you don't care. + * @param msgListener If you want to be warn on the send status of the message. Use null if you don't care. * @return Return true if the message went to the transport to be delivered. If you need to know if the message left * the transport use the listener. */ diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java new file mode 100644 index 0000000000..7968472b7d --- /dev/null +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) + * All rights reserved. + * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal + * + * This file is part of Neptus, Command and Control Framework. + * + * Commercial Licence Usage + * Licencees holding valid commercial Neptus licences may use this file + * in accordance with the commercial licence agreement provided with the + * Software or, alternatively, in accordance with the terms contained in a + * written agreement between you and Universidade do Porto. For licensing + * terms, conditions, and further information contact lsts@fe.up.pt. + * + * Modified European Union Public Licence - EUPL v.1.1 Usage + * Alternatively, this file may be used under the terms of the Modified EUPL, + * Version 1.1 only (the "Licence"), appearing in the file LICENSE.md + * included in the packaging of this file. You may not use this work + * except in compliance with the Licence. Unless required by applicable + * law or agreed to in writing, software distributed under the Licence is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific + * language governing permissions and limitations at + * https://github.com/LSTS/neptus/blob/develop/LICENSE.md + * and http://ec.europa.eu/idabc/eupl.html. + * + * For more information please see . + * + * Author: Paulo Dias + * 15/4/2024 + */ +package pt.lsts.neptus.comm.manager.imc; + +import pt.lsts.imc.Announce; +import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.messages.listener.MessageInfo; +import pt.lsts.neptus.types.coord.LocationType; +import pt.lsts.neptus.util.conf.GeneralPreferences; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.time.Duration; +import java.time.LocalTime; +import java.util.LinkedHashMap; +import java.util.Map; + +import static pt.lsts.neptus.comm.manager.imc.ImcMsgManager.DEFAULT_UDP_VEH_PORT; + +public class ImcMsgManagerAnnounceProcessor { + private ImcMsgManager manager; + + public ImcMsgManagerAnnounceProcessor(ImcMsgManager manager) { + this.manager = manager; + } + + /** + * @param info + * @param ann + * @param vci + * @param id + * @return + * @throws IOException + */ + SystemImcMsgCommInfo processAnnounceMessage(MessageInfo info, Announce ann, SystemImcMsgCommInfo vci, + ImcId16 id) throws IOException { + + LocalTime timeStart = LocalTime.now(); + + String sia = info.getPublisherInetAddress(); + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: publisher host address " + sia); + + boolean hostWasGuessed = true; + + InetSocketAddress[] retId = manager.announceWorker.getImcIpsPortsFromMessageImcUdp(ann); + int portUdp = 0; + String hostUdp = ""; + boolean udpIpPortFound = false; + if (retId.length > 0) { + portUdp = retId[0].getPort(); + hostUdp = retId[0].getAddress().getHostAddress(); + } + for (InetSocketAddress add : retId) { + if (sia.equalsIgnoreCase(add.getAddress().getHostAddress())) { + if (ReachableCache.firstReachable(GeneralPreferences.imcReachabilityTestTimeout, add) != null) { + udpIpPortFound = true; + portUdp = add.getPort(); + hostUdp = add.getAddress().getHostAddress(); + hostWasGuessed = false; + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "UDP reachable @ " + hostUdp + ":" + portUdp); + break; + } + } + } + + // Let us try to know any one in the announce IPs + if (portUdp > 0 && !udpIpPortFound) { + InetSocketAddress reachableAddr = ReachableCache.firstReachable(GeneralPreferences.imcReachabilityTestTimeout, retId); + if (reachableAddr != null) { + udpIpPortFound = true; + portUdp = reachableAddr.getPort(); + hostUdp = reachableAddr.getAddress().getHostAddress(); + hostWasGuessed = false; + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "UDP reachable @ " + hostUdp + ":" + portUdp); + } + } + + if (portUdp > 0 && !udpIpPortFound) { + // Lets try to see if we received a message from any of the IPs + String ipReceived = hostUdp.isEmpty() ? info.getPublisherInetAddress() : hostUdp; + hostWasGuessed = hostUdp.isEmpty() ? hostWasGuessed : true; + hostUdp = ipReceived; + udpIpPortFound = true; + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "no UDP reachable using " + hostUdp + ":" + portUdp); + } + + InetSocketAddress[] retIdT = manager.announceWorker.getImcIpsPortsFromMessageImcTcp(ann); + int portTcp = 0; + boolean tcpIpPortFound = false; + if (retIdT.length > 0) { + portTcp = retIdT[0].getPort(); + if ("".equalsIgnoreCase(hostUdp)) + hostUdp = retIdT[0].getAddress().getHostAddress(); + } + for (InetSocketAddress add : retIdT) { + if (sia.equalsIgnoreCase(add.getAddress().getHostAddress())) { + if ("".equalsIgnoreCase(hostUdp)) { + if (ReachableCache.firstReachable(GeneralPreferences.imcReachabilityTestTimeout, add) != null) { + tcpIpPortFound = true; + hostUdp = add.getAddress().getHostAddress(); + hostWasGuessed = false; + portTcp = add.getPort(); + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "TCP reachable @ " + hostUdp + ":" + portTcp); + break; + } + else + continue; + } + portTcp = add.getPort(); + tcpIpPortFound = true; + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "no TCP reachable using " + hostUdp + ":" + portTcp); + break; + } + } + + // Let us try to know any one in the announce IPs + if (portTcp > 0 && !tcpIpPortFound) { + InetSocketAddress reachableAddr = ReachableCache.firstReachable(GeneralPreferences.imcReachabilityTestTimeout, retId); + if (reachableAddr != null) { + if ("".equalsIgnoreCase(hostUdp)) { + tcpIpPortFound = true; + hostUdp = reachableAddr.getAddress().getHostAddress(); + hostWasGuessed = false; + portTcp = reachableAddr.getPort(); + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "TCP reachable @ " + hostUdp + ":" + portTcp); + } + portTcp = reachableAddr.getPort(); + tcpIpPortFound = true; + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "no TCP reachable using " + hostUdp + ":" + portTcp); + } + } + + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "using UDP@" + hostUdp + + ":" + portUdp + " and using TCP@" + hostUdp + ":" + portTcp + " with host " + + (hostWasGuessed ? "guessed" : "found")); + + boolean requestEntityList = false; + if (vci == null) { + // Create a new system + vci = manager.initSystemCommInfo(id, info.getPublisherInetAddress() + ":" + + (portUdp == 0 ? DEFAULT_UDP_VEH_PORT : portUdp)); + manager.updateUdpOnIpMapper(vci); + requestEntityList = true; + } + // announceWorker.processAnnouceMessage(msg); + String name = ann.getSysName(); + String type = ann.getSysType().toString(); + vci.setSystemIdName(name); + ImcSystem resSys = ImcSystemsHolder.lookupSystem(id); + // NeptusLog.pub().info("<###>......................Announce..." + name + " | " + type + " :: " + hostUdp + " " + + // portUdp); + // NeptusLog.pub().warn(ReflectionUtil.getCallerStamp()+ " ..........................| " + name + " | " + type); + if (resSys != null) { + resSys.setServicesProvided(manager.announceWorker.getImcServicesFromMessage(ann)); + AnnounceWorker.processUidFromServices(resSys); + + // new 2012-06-23 + if (resSys.isOnIdErrorState()) { + EntitiesResolver.clearAliases(resSys.getName()); + EntitiesResolver.clearAliases(resSys.getId()); + } + + resSys.setName(name); + resSys.setType(ImcSystem.translateSystemTypeFromMessage(type)); + resSys.setTypeVehicle(ImcSystem.translateVehicleTypeFromMessage(type)); + // NeptusLog.pub().info(ReflectionUtil.getCallerStamp()+ " ------------------------| " + resSys.getName() + + // " | " + resSys.getType()); + if (portUdp != 0 && udpIpPortFound) { + resSys.setRemoteUDPPort(portUdp); + } + else { + if (resSys.getRemoteUDPPort() == 0) + resSys.setRemoteUDPPort(DEFAULT_UDP_VEH_PORT); + } + if (!"".equalsIgnoreCase(hostUdp) && !AnnounceWorker.NONE_IP.equalsIgnoreCase(hostUdp)) { +// hostWasGuessed = true; + if (AnnounceWorker.USE_REMOTE_IP.equalsIgnoreCase(hostUdp)) { + if (manager.dontIgnoreIpSourceRequest) + resSys.setHostAddress(info.getPublisherInetAddress()); + } + else { + if ((udpIpPortFound || tcpIpPortFound) && !hostWasGuessed) { + resSys.setHostAddress(hostUdp); + } + else if (hostWasGuessed) { + boolean alreadyFound = false; + try { + Map fAddr = new LinkedHashMap<>(); + InetAddress publisherIAddr = InetAddress.getByName(sia); + byte[] pba = publisherIAddr.getAddress(); + int i = 0; + for (InetSocketAddress inetSAddr : retId) { + byte[] lta = inetSAddr.getAddress().getAddress(); + if (lta.length != pba.length) + continue; + i = 0; + for (; i < lta.length; i++) { + if (pba[i] != lta[i]) + break; + } + if (i > 0 && i <= pba.length) + fAddr.put(inetSAddr, i); + } + for (InetSocketAddress inetSAddr : retIdT) { + if (fAddr.containsKey(inetSAddr)) + continue; + byte[] lta = inetSAddr.getAddress().getAddress(); + if (lta.length != pba.length) + continue; + i = 0; + for (; i < lta.length; i++) { + if (pba[i] != lta[i]) + break; + } + if (i > 0 && i <= pba.length) + fAddr.put(inetSAddr, i); + } + + InetSocketAddress foundCandidateAddr = fAddr.keySet().stream().max((a1, a2) -> { + return fAddr.get(a1) - fAddr.get(a2); + }).orElse(null); + if (foundCandidateAddr != null) { + resSys.setHostAddress(foundCandidateAddr.getAddress().getHostAddress()); + alreadyFound = true; + } + } + catch (Exception e) { + e.printStackTrace(); + } + + if (!alreadyFound) { + String curHostAddr = resSys.getHostAddress(); + boolean currIsInAnnounce = false; + for (InetSocketAddress inetSAddr : retId) { + if (curHostAddr.equalsIgnoreCase(inetSAddr.getAddress().getHostAddress())) { + currIsInAnnounce = true; + break; + } + } + if (!currIsInAnnounce) { + for (InetSocketAddress inetSAddr : retIdT) { + if (curHostAddr.equalsIgnoreCase(inetSAddr.getAddress().getHostAddress())) { + currIsInAnnounce = true; + break; + } + } + } + + if (!currIsInAnnounce) + resSys.setHostAddress(hostUdp); + } + } + } + } + if (portTcp != 0 && tcpIpPortFound) { + resSys.setTCPOn(true); + resSys.setRemoteTCPPort(portTcp); + } + else if (portTcp == 0) { + resSys.setTCPOn(false); + } + + if (resSys.isTCPOn() && retId.length == 0) { + resSys.setUDPOn(false); + } + else { + resSys.setUDPOn(true); + } + + NeptusLog.pub().debug("processAnnounceMessage for " + ann.getSysName() + "@" + id + " :: " + "final setup UDP@" + resSys.getHostAddress() + + ":" + resSys.getRemoteUDPPort() + " and using TCP@" + resSys.getHostAddress() + ":" + resSys.getRemoteTCPPort()); + + resSys.setOnAnnounceState(true); + + try { + double latRad = ann.getLat(); + double lonRad = ann.getLon(); + double height = ann.getHeight(); + if (latRad != 0 && lonRad != 0) { + LocationType loc = new LocationType(); + loc.setLatitudeDegs(Math.toDegrees(latRad)); + loc.setLongitudeDegs(Math.toDegrees(lonRad)); + loc.setHeight(height); + long locTime = (long) (info.getTimeSentSec() * 1000); + resSys.setLocation(loc, locTime); + } + } + catch (Exception e) { + e.printStackTrace(); + } + + // Adding temp getting heading from services + double headingDegreesFromServices = AnnounceWorker.processHeadingDegreesFromServices(resSys); + if (!Double.isNaN(headingDegreesFromServices) && !Double.isInfinite(headingDegreesFromServices)) { + long attTime = (long) (info.getTimeSentSec() * 1000); + resSys.setAttitudeDegrees(headingDegreesFromServices, attTime); + } + + Map er = EntitiesResolver.getEntities(resSys.getName()); + if (er == null || er.size() == 0) + requestEntityList = true; + + if (requestEntityList) + manager.announceWorker.sendEntityListRequestMsg(resSys); + + ImcSystemsHolder.registerSystem(resSys); + } + + Duration deltaT = Duration.between(timeStart, LocalTime.now()); + if (deltaT.getSeconds() > 1) { + NeptusLog.pub().warn("=====!!===== Too long processing announce DF " + deltaT + " :: " + ann.getAbbrev() + + " @ " + new ImcId16(ann.getSrc()).toPrettyString() + "\n=====!!===== Try reducing " + + "'General Preference->[IMC Communications]-> Reachability Test Timeout' from " + + GeneralPreferences.imcReachabilityTestTimeout + + " to in the order of tens or 1 or 2 hundreds of ms."); + } + + manager.imcDefinition.getResolver().addEntry(ann.getSrc(), ann.getSysName()); + return vci; + } +} diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java new file mode 100644 index 0000000000..8fa9abf6be --- /dev/null +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) + * All rights reserved. + * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal + * + * This file is part of Neptus, Command and Control Framework. + * + * Commercial Licence Usage + * Licencees holding valid commercial Neptus licences may use this file + * in accordance with the commercial licence agreement provided with the + * Software or, alternatively, in accordance with the terms contained in a + * written agreement between you and Universidade do Porto. For licensing + * terms, conditions, and further information contact lsts@fe.up.pt. + * + * Modified European Union Public Licence - EUPL v.1.1 Usage + * Alternatively, this file may be used under the terms of the Modified EUPL, + * Version 1.1 only (the "Licence"), appearing in the file LICENSE.md + * included in the packaging of this file. You may not use this work + * except in compliance with the Licence. Unless required by applicable + * law or agreed to in writing, software distributed under the Licence is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific + * language governing permissions and limitations at + * https://github.com/LSTS/neptus/blob/develop/LICENSE.md + * and http://ec.europa.eu/idabc/eupl.html. + * + * For more information please see . + * + * Author: Paulo Dias + * 15/4/2024 + */ +package pt.lsts.neptus.comm.manager.imc; + +import pt.lsts.imc.AssetReport; +import pt.lsts.imc.EntityInfo; +import pt.lsts.imc.EntityList; +import pt.lsts.imc.FuelLevel; +import pt.lsts.imc.IMCMessage; +import pt.lsts.imc.MessagePart; +import pt.lsts.imc.PlanControlState; +import pt.lsts.imc.RemoteSensorInfo; +import pt.lsts.imc.ReportedState; +import pt.lsts.imc.StateReport; +import pt.lsts.imc.net.IMCFragmentHandler; +import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.comm.IMCUtils; +import pt.lsts.neptus.comm.SystemUtils; +import pt.lsts.neptus.messages.listener.MessageInfo; +import pt.lsts.neptus.systems.external.ExternalSystem; +import pt.lsts.neptus.systems.external.ExternalSystemsHolder; +import pt.lsts.neptus.types.coord.LocationType; +import pt.lsts.neptus.types.vehicle.VehicleType; +import pt.lsts.neptus.util.AngleUtils; +import pt.lsts.neptus.util.MathMiscUtils; + +import java.util.ArrayList; +import java.util.Collections; + +class ImcMsgManagerMessageProcessor { + private final ImcMsgManager manager; + private final IMCFragmentHandler fragmentHandler; + + public ImcMsgManagerMessageProcessor(ImcMsgManager manager) { + this.manager = manager; + fragmentHandler = new IMCFragmentHandler(manager.imcDefinition); + } + + void processEntityInfo(MessageInfo info, EntityInfo msg) { + manager.imcDefinition.getResolver().setEntityName(msg.getSrc(), msg.getSrcEnt(), msg.getLabel()); + } + + void processMessagePart(MessageInfo info, MessagePart msg) { + IMCMessage m = fragmentHandler.setFragment((MessagePart)msg); + if (m != null) + manager.postInternalMessage(msg.getSourceName(), m); + } + + void processEntityList(ImcId16 id, MessageInfo info, EntityList msg) { + EntitiesResolver.setEntities(id.toString(), msg); + manager.imcDefinition.getResolver().setEntityMap(msg.getSrc(), msg.getList()); + ImcSystem sys = ImcSystemsHolder.lookupSystem(id); + if (sys != null) { + EntitiesResolver.setEntities(sys.getName(), msg); + } + } + + void processReportedState(MessageInfo info, ReportedState msg) { + // Process pos. state reported from other system + String sysId = msg.getSid(); + + double latRad = msg.getLat(); + double lonRad = msg.getLon(); + double depth = msg.getDepth(); + + double rollRad = msg.getRoll(); + double pitchRad = msg.getPitch(); + double yawRad = msg.getYaw(); + + double recTimeSecs = msg.getRcpTime(); + long recTimeMillis = Double.isFinite(recTimeSecs) ? (long) (recTimeSecs * 1E3) : msg.getTimestampMillis(); + + // msg.getSType(); // Not used + + ImcSystem imcSys = ImcSystemsHolder.lookupSystemByName(sysId); + ExternalSystem extSys = null; + if (imcSys == null) { + extSys = ExternalSystemsHolder.lookupSystem(sysId); + if (extSys == null) { + extSys = new ExternalSystem(sysId); + ExternalSystemsHolder.registerSystem(extSys); + } + } + + if (Double.isFinite(latRad) && Double.isFinite(lonRad)) { + LocationType loc = new LocationType(Math.toDegrees(latRad), Math.toDegrees(lonRad)); + if (Double.isFinite(depth)) + loc.setDepth(depth); + + if (imcSys != null) + imcSys.setLocation(loc, recTimeMillis); + else + extSys.setLocation(loc, recTimeMillis); + } + + if (Double.isFinite(rollRad) || Double.isFinite(pitchRad) || Double.isFinite(yawRad)) { + double rollDeg = Double.isFinite(rollRad) ? Math.toDegrees(rollRad) : 0; + double pitchDeg = Double.isFinite(pitchRad) ? Math.toDegrees(pitchRad) : 0; + double yawDeg = Double.isFinite(yawRad) ? Math.toDegrees(yawRad) : 0; + + if (imcSys != null) + imcSys.setAttitudeDegrees(rollDeg, pitchDeg, yawDeg, recTimeMillis); + else + extSys.setAttitudeDegrees(rollDeg, pitchDeg, yawDeg, recTimeMillis); + } + } + + void processStateReport(MessageInfo info, StateReport msg, ArrayList messagesCreatedToFoward) { + + String sysId = msg.getSourceName(); + + long dataTimeMillis = msg.getStime() * 1000; + + double lat = msg.getLatitude(); + double lon = msg.getLongitude(); + double depth = msg.getDepth() == 0xFFFF ? -1 : msg.getDepth() / 10.0; + // double altitude = msg.getAltitude() == 0xFFFF ? -1 : msg.getAltitude() / 10.0; + double heading = ((double)msg.getHeading() / 65535.0) * 360; + double speedMS = msg.getSpeed() / 100.; + NeptusLog.pub().info("Received report from "+msg.getSourceName()); + + ImcSystem imcSys = ImcSystemsHolder.lookupSystemByName(sysId); + if (imcSys == null) { + NeptusLog.pub().error("Could not find system with id "+sysId); + return; + } + + LocationType loc = new LocationType(lat, lon); + loc.setDepth(depth); + imcSys.setLocation(loc, dataTimeMillis); + imcSys.setAttitudeDegrees(heading, dataTimeMillis); + + imcSys.storeData(SystemUtils.GROUND_SPEED_KEY, speedMS, dataTimeMillis, true); + imcSys.storeData(SystemUtils.COURSE_DEGS_KEY, + (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(heading, 0)), + dataTimeMillis, true); + imcSys.storeData( + SystemUtils.HEADING_DEGS_KEY, + (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(heading, 0)), + dataTimeMillis, true); + + int fuelPerc = msg.getFuel(); + if (fuelPerc > 0) { + FuelLevel fuelLevelMsg = new FuelLevel(); + IMCUtils.copyHeader(msg, fuelLevelMsg); + fuelLevelMsg.setTimestampMillis(dataTimeMillis); + fuelLevelMsg.setValue(fuelPerc); + fuelLevelMsg.setConfidence(0); + imcSys.storeData(SystemUtils.FUEL_LEVEL_KEY, fuelLevelMsg, dataTimeMillis, true); + + messagesCreatedToFoward.add(fuelLevelMsg); + } + + int execState = msg.getExecState(); + PlanControlState pcsMsg = new PlanControlState(); + IMCUtils.copyHeader(msg, pcsMsg); + pcsMsg.setTimestampMillis(dataTimeMillis); + switch (execState) { + case -1: + pcsMsg.setState(PlanControlState.STATE.READY); + break; + case -3: + pcsMsg.setState(PlanControlState.STATE.INITIALIZING); + break; + case -2: + case -4: + pcsMsg.setState(PlanControlState.STATE.BLOCKED); + break; + default: + if (execState > 0) + pcsMsg.setState(PlanControlState.STATE.EXECUTING); + else + pcsMsg.setState(PlanControlState.STATE.BLOCKED); + break; + } + + pcsMsg.setPlanEta(-1); + pcsMsg.setPlanProgress(execState >= 0 ? execState : -1); + pcsMsg.setManId(""); + pcsMsg.setManEta(-1); + pcsMsg.setManType(0xFFFF); + + messagesCreatedToFoward.add(pcsMsg); + } + + void processAssetReport(MessageInfo info, AssetReport msg, ArrayList messagesCreatedToFoward) { + + String reporterId = msg.getSourceName(); + String sysId = msg.getName(); + + long dataTimeMillis = Double.valueOf(msg.getReportTime() * 1000).longValue(); + + AssetReport.MEDIUM mediumReported = msg.getMedium(); + + double latRad = msg.getLat(); + double lonRad = msg.getLon(); + double depth = msg.getDepth(); + double altitude = msg.getAlt(); + + double speedMS = msg.getSog(); + double cogRads = msg.getCog(); + + ArrayList otherMsgs = Collections.list(msg.getMsgs().elements()); // TODO + + ImcSystem imcSys = ImcSystemsHolder.lookupSystemByName(sysId); + ExternalSystem extSys = null; + if (imcSys == null) { + extSys = ExternalSystemsHolder.lookupSystem(sysId); + if (extSys == null) { + extSys = new ExternalSystem(sysId); + ExternalSystemsHolder.registerSystem(extSys); + } + } + + if (Double.isFinite(latRad) && Double.isFinite(lonRad)) { + LocationType loc = new LocationType(AngleUtils.nomalizeAngleDegrees180(Math.toDegrees(latRad)), + AngleUtils.nomalizeAngleDegrees180(Math.toDegrees(lonRad))); + if (Double.isFinite(depth)) { + loc.setDepth(depth); + } + if (imcSys != null) { + imcSys.setLocation(loc, dataTimeMillis); + } else { + extSys.setLocation(loc, dataTimeMillis); + } + } + double headingRads = Double.NaN; + if (Double.isFinite(cogRads) && Double.isFinite(speedMS) && Math.abs(speedMS) > 0.2) { + headingRads = AngleUtils.nomalizeAngleRads2Pi(cogRads * (speedMS < 0 ? -1 : 1)); + if (imcSys != null) { + imcSys.setAttitudeDegrees(headingRads, dataTimeMillis); + imcSys.storeData( + SystemUtils.HEADING_DEGS_KEY, + (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(Math.toDegrees(headingRads), 0)), + dataTimeMillis, true); + } else { + extSys.setAttitudeDegrees(headingRads, dataTimeMillis); + extSys.storeData( + SystemUtils.HEADING_DEGS_KEY, + (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(Math.toDegrees(headingRads), 0)), + dataTimeMillis, true); + } + } + + if (imcSys != null) { + imcSys.storeData(SystemUtils.GROUND_SPEED_KEY, speedMS, dataTimeMillis, true); + imcSys.storeData(SystemUtils.COURSE_DEGS_KEY, + (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(Math.toDegrees(cogRads), 0)), + dataTimeMillis, true); + } else { + extSys.storeData(SystemUtils.GROUND_SPEED_KEY, speedMS, dataTimeMillis, true); + extSys.storeData(SystemUtils.COURSE_DEGS_KEY, + (int) AngleUtils.nomalizeAngleDegrees360(MathMiscUtils.round(Math.toDegrees(cogRads), 0)), + dataTimeMillis, true); + } + } + + void processRemoteSensorInfo(MessageInfo info, RemoteSensorInfo msg) { + // Process pos. state reported from other system + String sysId = msg.getId(); + + double latRad = msg.getLat(); + double lonRad = msg.getLon(); + double altitude = msg.getAlt(); + + double headingRad = msg.getHeading(); + + String sensorClass = msg.getSensorClass(); + + long recTimeMillis = msg.getTimestampMillis(); + + ImcSystem imcSys = ImcSystemsHolder.lookupSystemByName(sysId); + ExternalSystem extSys = null; + if (imcSys == null) { + extSys = ExternalSystemsHolder.lookupSystem(sysId); + if (extSys == null) { + extSys = new ExternalSystem(sysId); + ExternalSystemsHolder.registerSystem(extSys); + } + } + + if (Double.isFinite(latRad) && Double.isFinite(lonRad)) { + LocationType loc = new LocationType(Math.toDegrees(latRad), Math.toDegrees(lonRad)); + if (Double.isFinite(altitude)) + loc.setDepth(-altitude); + + if (imcSys != null) + imcSys.setLocation(loc, recTimeMillis); + else + extSys.setLocation(loc, recTimeMillis); + } + + if (Double.isFinite(headingRad)) { + double headingDeg = Math.toDegrees(headingRad); + + if (imcSys != null) + imcSys.setAttitudeDegrees(headingDeg, recTimeMillis); + else + extSys.setAttitudeDegrees(headingDeg, recTimeMillis); + } + + // Process sensor class + VehicleType.SystemTypeEnum type = SystemUtils.getSystemTypeFrom(sensorClass); + VehicleType.VehicleTypeEnum typeVehicle = SystemUtils.getVehicleTypeFrom(sensorClass); + ExternalSystem.ExternalTypeEnum typeExternal = SystemUtils.getExternalTypeFrom(sensorClass); + if (imcSys != null) { + imcSys.setType(type); + imcSys.setTypeVehicle(typeVehicle); + } + else { + extSys.setType(type); + extSys.setTypeVehicle(typeVehicle); + extSys.setTypeExternal(typeExternal); + } + } +} From 9e12db7468f5e7d37365acca37434be4455cca9d Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 15 Apr 2024 11:22:10 +0100 Subject: [PATCH 02/92] comm/manager/imc/ImcMsgManagerAnnounceProcessor: Little cleanup. --- .../comm/manager/imc/ImcMsgManagerAnnounceProcessor.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java index 7968472b7d..319a23b5c0 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java @@ -49,7 +49,7 @@ import static pt.lsts.neptus.comm.manager.imc.ImcMsgManager.DEFAULT_UDP_VEH_PORT; public class ImcMsgManagerAnnounceProcessor { - private ImcMsgManager manager; + private final ImcMsgManager manager; public ImcMsgManagerAnnounceProcessor(ImcMsgManager manager) { this.manager = manager; @@ -107,7 +107,7 @@ SystemImcMsgCommInfo processAnnounceMessage(MessageInfo info, Announce ann, Syst } if (portUdp > 0 && !udpIpPortFound) { - // Lets try to see if we received a message from any of the IPs + // Let's try to see if we received a message from any of the IPs String ipReceived = hostUdp.isEmpty() ? info.getPublisherInetAddress() : hostUdp; hostWasGuessed = hostUdp.isEmpty() ? hostWasGuessed : true; hostUdp = ipReceived; @@ -328,7 +328,7 @@ else if (portTcp == 0) { } Map er = EntitiesResolver.getEntities(resSys.getName()); - if (er == null || er.size() == 0) + if (er == null || er.isEmpty()) requestEntityList = true; if (requestEntityList) From fbd0d8c885da0c216f31d09fd1feb5f970c8c72f Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 17 Apr 2024 10:56:04 +0100 Subject: [PATCH 03/92] util/conf/GeneralPreferences: Fix typos. --- .../neptus/util/conf/GeneralPreferences.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java b/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java index 32be371dd6..fbddec06ff 100644 --- a/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java +++ b/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java @@ -122,7 +122,7 @@ public class GeneralPreferences implements PropertiesProvider { description = "If enable allows the announce msg request to use the sender IP to be use in future comms. to the sender system.") public static boolean imcChangeBySourceIpRequest = true; - @NeptusProperty(name = "IMC Unicast Annonce Enable", category = "IMC Communications", userLevel = LEVEL.ADVANCED, + @NeptusProperty(name = "IMC Unicast Announce Enable", category = "IMC Communications", userLevel = LEVEL.ADVANCED, description = "To send announce also by Unicast. Enable or disable") public static boolean imcUnicastAnnounceEnable = true; @@ -134,7 +134,7 @@ public class GeneralPreferences implements PropertiesProvider { // ------------------------------------------------------------------------- - @NeptusProperty(name = "Logs Downloader - Enable Parcial Download", category = "IMC Logs Downloader", userLevel = LEVEL.ADVANCED, + @NeptusProperty(name = "Logs Downloader - Enable Partial Download", category = "IMC Logs Downloader", userLevel = LEVEL.ADVANCED, description = "Enable the partial logs downloads (resume partial downloads). NOTE: THE DOWNLOAD BOXES ONLY READ THIS OPTION UPON CREATION.") public static boolean logsDownloaderEnablePartialDownload = true; @@ -197,15 +197,15 @@ public class GeneralPreferences implements PropertiesProvider { description = "Select the comms. queues size.") public static int commsQueueSize = 1024; - @NeptusProperty(name = "Comms. Messsage Separation Time (ms)", category = "Communications", userLevel = LEVEL.ADVANCED, - description = "Select the comms. separation time in miliseconds that a message (by type) should be warn. Use \"-1\" for always warn.") + @NeptusProperty(name = "Comms. Message Separation Time (ms)", category = "Communications", userLevel = LEVEL.ADVANCED, + description = "Select the comms. separation time in milliseconds that a message (by type) should be warn. Use \"-1\" for always warn.") public static int commsMsgSeparationMillis = -1; @NeptusProperty(name = "Filter UDP Redirect Also By Port", editable = false, category = "IMC Communications", userLevel = LEVEL.ADVANCED) public static boolean filterUdpAlsoByPort = false; @NeptusProperty(name = "Redirect Unknown Comms. To First Vehicle In Comm. List", editable = false, category = "IMC Communications", userLevel = LEVEL.ADVANCED, - description = "Any messages comming from unknown vehicle will be redirect to the first on comm. list.") + description = "Any messages coming from unknown vehicle will be redirect to the first on comm. list.") public static boolean redirectUnknownIdsToFirstCommVehicle = false; @@ -244,22 +244,24 @@ public class GeneralPreferences implements PropertiesProvider { // ------------------------------------------------------------------------- @NeptusProperty(name = "Place Main Vehicle Combobox On Menu Or Status Bar", category="Console", userLevel = LEVEL.REGULAR, - description = "Place the console vehicle combobox on the menu bar or status bar (overcomes Unity hidding menus).") + description = "Place the console vehicle combobox on the menu bar or status bar (overcomes Unity hiding menus).") public static boolean placeMainVehicleComboOnMenuOrStatusBar = true; @NeptusProperty(name = "Use Main Vehicle Combo on Consoles", category="Console", userLevel = LEVEL.ADVANCED, - description = "Needs console retarts.") + description = "Needs console restarts.") public static boolean useMainVehicleComboOnConsoles = true; @NeptusProperty(name = "Place Notification Button on Console Status Bar", category="Console", userLevel = LEVEL.ADVANCED, - description = "Needs console retarts.") + description = "Needs console restarts.") public static boolean placeNotificationButtonOnConsoleStatusBar = true; // ------------------------------------------------------------------------- + @Deprecated @NeptusProperty(name = "AIS MMSI Query Prefix", category = "AIS MMSI Query", userLevel = LEVEL.ADVANCED) public static String aisMmsiQueryUrlPrefix = "http://api.ais.owm.io/1.2/vessels/"; - + + @Deprecated @NeptusProperty(name = "AIS MMSI Query Sufix", category = "AIS MMSI Query", userLevel = LEVEL.ADVANCED) public static String aisMmsiQueryUrlSufix = ".json?api_key=f7a0da8eacb49740eb45b5e74d130459"; @@ -277,7 +279,7 @@ public class GeneralPreferences implements PropertiesProvider { @NeptusProperty(name = "Preferred Z Units Array", category = "Z Value", userLevel = LEVEL.ADVANCED, editable = false, rendererClass = ArrayAsStringRenderer.class, - description = "This lists the valid Z units to show. This can be overided by the per vehicle settings. " + description = "This lists the valid Z units to show. This can be override by the per vehicle settings. " + "Leeave it empty for no restrictions.") public static ManeuverLocation.Z_UNITS[] validZUnits = {}; From 2de44d5404531769e0bd3fffc8a93a044c446549 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 24 Apr 2024 10:34:19 +0100 Subject: [PATCH 04/92] comm/iridium/RockBlockIridiumMessenger: Small fix to not give error due to certificate error for https (this is just see if we can reach). --- .../pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java index e3bb4c090e..c374f04896 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java @@ -378,7 +378,7 @@ public static Future rockBlockIsReachable() { } try { - URL url = new URL("https://secure.rock7mobile.com/rockblock"); + URL url = new URL("http://secure.rock7mobile.com/rockblock"); int len = url.openConnection().getContentLength(); if (len > 0) lastSuccess = System.currentTimeMillis(); From 326db8b82b481fd3c3b9daa339964609f9c09e4d Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 16 May 2024 18:45:14 +0100 Subject: [PATCH 05/92] comm/admin/CommsAdmin: WIP for adding channels support for comms with vehicles offline. --- .../lsts/neptus/comm/IMCSendMessageUtils.java | 9 +- .../pt/lsts/neptus/comm/admin/CommsAdmin.java | 409 ++++++++++++++++++ .../comm/manager/imc/ImcMsgManager.java | 75 +++- .../neptus/util/conf/GeneralPreferences.java | 12 + 4 files changed, 488 insertions(+), 17 deletions(-) create mode 100644 src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java diff --git a/src/java/pt/lsts/neptus/comm/IMCSendMessageUtils.java b/src/java/pt/lsts/neptus/comm/IMCSendMessageUtils.java index 4fe11efcdb..833dbbaeb8 100644 --- a/src/java/pt/lsts/neptus/comm/IMCSendMessageUtils.java +++ b/src/java/pt/lsts/neptus/comm/IMCSendMessageUtils.java @@ -60,6 +60,7 @@ import pt.lsts.neptus.types.vehicle.VehicleType.SystemTypeEnum; import pt.lsts.neptus.util.GuiUtils; import pt.lsts.neptus.util.StringUtils; +import pt.lsts.neptus.util.conf.GeneralPreferences; /** * @author pdias @@ -148,7 +149,13 @@ public static boolean sendMessage(IMCMessage msg, String sendProperties, Message for (String sid : ids) { boolean ret; ImcSystem sysL = ImcSystemsHolder.lookupSystemByName(sid); - if (acousticOpSysLst.length != 0 && sysL != null && !sysL.isActive()) { + if (GeneralPreferences.imcUseNewMultiChannelCommsEnable && sysL != null && !sysL.isActive()) { + ret = ImcMsgManager.getManager().sendMessageUsingActiveChannelWait(msg, sid, -1, parent, acousticOpUserAprovedQuestion); + if (ret) { + acousticOpUserAproved = true; + } + } + else if (acousticOpSysLst.length != 0 && sysL != null && !sysL.isActive()) { if (acousticOpUserAprovalRequired) { acousticOpUserAproved = (GuiUtils.confirmDialog(parent, I18n.text("Send by Acoustic Modem"), I18n.text("Some systems are not active. Do you want to send by acoustic modem?")) == JOptionPane.YES_OPTION); diff --git a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java new file mode 100644 index 0000000000..16934b2c56 --- /dev/null +++ b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) + * All rights reserved. + * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal + * + * This file is part of Neptus, Command and Control Framework. + * + * Commercial Licence Usage + * Licencees holding valid commercial Neptus licences may use this file + * in accordance with the commercial licence agreement provided with the + * Software or, alternatively, in accordance with the terms contained in a + * written agreement between you and Universidade do Porto. For licensing + * terms, conditions, and further information contact lsts@fe.up.pt. + * + * Modified European Union Public Licence - EUPL v.1.1 Usage + * Alternatively, this file may be used under the terms of the Modified EUPL, + * Version 1.1 only (the "Licence"), appearing in the file LICENSE.md + * included in the packaging of this file. You may not use this work + * except in compliance with the Licence. Unless required by applicable + * law or agreed to in writing, software distributed under the Licence is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific + * language governing permissions and limitations at + * https://github.com/LSTS/neptus/blob/develop/LICENSE.md + * and http://ec.europa.eu/idabc/eupl.html. + * + * For more information please see . + * + * Author: Paulo Dias + * 16/4/2024 + */ +package pt.lsts.neptus.comm.admin; + +import pt.lsts.imc.IMCDefinition; +import pt.lsts.imc.IMCMessage; +import pt.lsts.imc.MessagePart; +import pt.lsts.imc.TransmissionRequest; +import pt.lsts.imc.net.IMCFragmentHandler; +import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.comm.IMCSendMessageUtils; +import pt.lsts.neptus.comm.iridium.ImcIridiumMessage; +import pt.lsts.neptus.comm.iridium.IridiumManager; +import pt.lsts.neptus.comm.manager.imc.ImcMsgManager; +import pt.lsts.neptus.comm.manager.imc.ImcSystem; +import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; +import pt.lsts.neptus.comm.manager.imc.MessageDeliveryListener; +import pt.lsts.neptus.types.vehicle.VehicleType; +import pt.lsts.neptus.util.conf.GeneralPreferences; + +import java.awt.Component; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +public class CommsAdmin { + + public static final int COMM_TIMEOUT_MILLIS = 20000; + public static final int MAX_ACOMMS_PAYLOAD_SIZE = 998; + public static final double TIMEOUT_ACOMMS_SECS = 60; + + public enum CommChannelType { + WIFI("WiFi", "Wi-Fi channel", "images/channels/wifi.png", + "images/channels/wifi_selected.png", "images/channels/wifi_disabled.png", true, false, false), + ACOUSTIC("Acoustic", "Acoustic channel", "images/channels/acoustic.png", + "images/channels/acoustic_selected.png", "images/channels/acoustic_disabled.png", true, false, false), + IRIDIUM("Iridium", "Iridium channel", "images/channels/iridium.png", + "images/channels/iridium_selected.png", "images/channels/iridium_disabled.png", true, false, false), + GSM("GSM", "GSM channel", "images/channels/gsm.png", + "images/channels/gsm_selected.png", "images/channels/gsm_disabled.png", true, false, false), + ; + + public final String name; + public final String description; + public final String icon; + public final String iconSelected; + public final String iconDisabled; + private boolean enabled; + private boolean active; + private boolean reliable; + + private CommChannelType(String name, String description, String icon, String iconSelected, + String iconDisabled, boolean enabled, boolean active, boolean reliable) { + this.name = name; + this.description = description; + this.icon = icon; + this.iconSelected = iconSelected; + this.iconDisabled = iconDisabled; + this.enabled = enabled; + this.active = active; + this.reliable = reliable; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + + public boolean isReliable() { + return reliable; + } + + public void setReliable(boolean reliable) { + this.reliable = reliable; + } + } // CommChannelType + + private final String acousticOpServiceName = "acoustic/operation"; + private final String iridiumOpServiceName = "iridium"; + + private ImcMsgManager imcMsgManager = null; + private List channels = new ArrayList<>(); + + public CommsAdmin(ImcMsgManager imcMsgManager) { + this.imcMsgManager = imcMsgManager; + + Collections.addAll(channels, CommChannelType.values()); + } + + //public static boolean sendMessage(IMCMessage msg, String sendProperties, MessageDeliveryListener listener, + // Component parent, String errorTextForDialog, String... destinationIds) { + + public Future sendMessage(IMCMessage message, String destinationName, int timeoutMillis, + Component parentComponentForAlert, + boolean requireUserConfirmOtherThanWifi, String... channelsToSend) { + final ResultWaiter waiter = new ResultWaiter(timeoutMillis); // COMM_TIMEOUT_MILLIS + FutureTask result = new FutureTask(waiter) { + private long start = System.currentTimeMillis(); + + @Override + public ImcMsgManager.SendResult get() throws InterruptedException, ExecutionException { + try { + return waiter.call(); + } catch (Exception e) { + throw new ExecutionException(e); + } + } + + @Override + public ImcMsgManager.SendResult get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, + TimeoutException { + long end = start + unit.toMillis(timeout); + while (System.currentTimeMillis() < end) { + if (waiter.result == null) { + Thread.sleep(100); + } else { + try { + return waiter.call(); + } catch (Exception e) { + throw new ExecutionException(e); + } + } + } + throw new TimeoutException("Time out exceeded"); + } + }; + + String channelsToUseConf = GeneralPreferences.imcChannelsToUse; + + //sendMessageToSystem(message, systemName, "TCP", waiter); + // Let us try to send the message to the destination + + // First check which channels are enabled here + List channelsToUse = new ArrayList<>(); + if (channelsToSend == null || channelsToSend.length == 0) { + channelsToUse.addAll(channels); + } else { + for (String channelName : channelsToSend) { + for (CommChannelType channel : channels) { + if (channel.name.equalsIgnoreCase(channelName)) { + channelsToUse.add(channel); + break; + } + } + } + } + + if (channelsToUse.isEmpty()) { + waiter.deliveryUnreacheable(message); + return result; + } + + final AtomicReference proxyAcousticSystem = new AtomicReference<>(); + final AtomicReference proxyGsmSystem = new AtomicReference<>(); + final AtomicReference proxyIridiumSystem = new AtomicReference<>(); + + ImcSystem system = ImcSystemsHolder.lookupSystemByName(destinationName); + + if (system == null) { + waiter.deliveryUnreacheable(message); + return result; + } + + // From the enabled channels, check which are active for the system + channelsToUse = channelsToUse.stream().filter(channel -> { + switch (channel) { + case WIFI: + if (system.isActive()) { + return true; + } + break; + case ACOUSTIC: + // Let's check if the system has this comm mean + + ImcSystem[] acousticOpSysLst = ImcSystemsHolder.lookupSystemByService( + acousticOpServiceName, VehicleType.SystemTypeEnum.ALL, true); + List canditatesList = Arrays.asList(acousticOpSysLst); + Collections.shuffle(canditatesList); + proxyAcousticSystem.set(canditatesList.stream().filter(sys -> IMCSendMessageUtils + .doesSystemWithAcousticCanReachSystem(sys, destinationName)) + .findFirst().orElse(null)); + if (proxyAcousticSystem.get() != null) { + return true; + } + break; + case IRIDIUM: + if (IridiumManager.getManager().isAvailable()) + return true; + break; + case GSM: + default: + break; + } + return false; + }).collect(Collectors.toList()); + + // We should now filter by the ones active for the system + + + // Now send the message to the first available channel + if (channelsToUse.isEmpty()) { + waiter.deliveryUnreacheable(message); + return result; + } + + // Try to check if the distance to vehícle is too far for the comm mean to be used + // **************************************************************************************** + + + // Send the message + for (CommChannelType channel : channelsToUse) { + switch (channel) { + case WIFI: + if (system.isActive()) { + imcMsgManager.sendMessage(message, system.getId(), null, waiter); + return result; + } + break; + case ACOUSTIC: + if (proxyAcousticSystem.get() != null && proxyAcousticSystem.get().isActive()) { + try { + ArrayList requests = new ArrayList(); + if (message.getPayloadSize() > MAX_ACOMMS_PAYLOAD_SIZE) { + IMCFragmentHandler handler = new IMCFragmentHandler(IMCDefinition.getInstance()); + + MessagePart[] parts = handler.fragment(message, MAX_ACOMMS_PAYLOAD_SIZE); + NeptusLog.pub().info("PlanDB message resulted in " + parts.length + " fragments"); + for (MessagePart part : parts) { + TransmissionRequest request = getAcousticTransmissionRequestForImcMessage(part, system); + requests.add(request); + } + } else { + TransmissionRequest request = getAcousticTransmissionRequestForImcMessage(message, system); + requests.add(request); + } + + for (TransmissionRequest request : requests) { + ImcMsgManager.getManager().sendMessageToSystem(request, proxyAcousticSystem.get().getName(), waiter); + } + + return result; + } catch (Exception e) { + NeptusLog.pub().error(this, e); + } + } + break; + case IRIDIUM: + sendViaIridium(proxyIridiumSystem.get().getName(), message, waiter); + return result; + case GSM: + default: + break; + } + } + + waiter.deliveryUnreacheable(message); + return result; + } + + private TransmissionRequest getAcousticTransmissionRequestForImcMessage(IMCMessage part, ImcSystem system) { + TransmissionRequest request = new TransmissionRequest(); + request.setCommMean(TransmissionRequest.COMM_MEAN.ACOUSTIC); + request.setReqId(Long.valueOf(imcMsgManager.getNextSeqInstanceNr()).intValue()); + request.setDataMode(TransmissionRequest.DATA_MODE.INLINEMSG); + request.setMsgData(part); + request.setDestination(system.getName()); + request.setDeadline(System.currentTimeMillis() / 1000.0 + TIMEOUT_ACOMMS_SECS); + return request; + } + + static class ResultWaiter implements Callable, MessageDeliveryListener { + + public ImcMsgManager.SendResult result = null; + private long timeoutMillis = 10000; + private long start; + + public ResultWaiter(long timeoutMillis) { + this.timeoutMillis = timeoutMillis; + this.start = System.currentTimeMillis(); + } + + @Override + public ImcMsgManager.SendResult call() throws Exception { + while (true) { + synchronized (this) { + if (result != null) { + return result; + } + if (System.currentTimeMillis() - start > timeoutMillis) { + return ImcMsgManager.SendResult.TIMEOUT; + } + } + Thread.sleep(100); + } + } + + @Override + public void deliveryError(IMCMessage message, Object error) { + result = ImcMsgManager.SendResult.ERROR; + } + + @Override + public void deliverySuccess(IMCMessage message) { + result = ImcMsgManager.SendResult.SUCCESS; + } + + @Override + public void deliveryTimeOut(IMCMessage message) { + result = ImcMsgManager.SendResult.TIMEOUT; + } + + @Override + public void deliveryUncertain(IMCMessage message, Object msg) { + result = ImcMsgManager.SendResult.UNCERTAIN_DELIVERY; + } + + @Override + public void deliveryUnreacheable(IMCMessage message) { + result = ImcMsgManager.SendResult.UNREACHABLE; + } + } + + public void sendViaIridium(String destination, IMCMessage message, ResultWaiter waiter) { + if (message.getTimestamp() == 0) + message.setTimestampMillis(System.currentTimeMillis()); + Collection irMsgs; + try { + irMsgs = IridiumManager.iridiumEncode(message); + } + catch (Exception e) { + NeptusLog.pub().warn( "Send by Iridium :: " + e.getMessage()); + waiter.deliveryError(message, e); + return; + } + int src = ImcMsgManager.getManager().getLocalId().intValue(); + int dst = IMCDefinition.getInstance().getResolver().resolve(destination); + int count = 0; + try { + NeptusLog.pub().warn(message.getAbbrev() + " resulted in " + irMsgs.size() + " iridium SBD messages."); + for (ImcIridiumMessage irMsg : irMsgs) { + irMsg.setDestination(dst); + irMsg.setSource(src); + irMsg.timestampMillis = message.getTimestampMillis(); + if (irMsg.timestampMillis == 0) + irMsg.timestampMillis = System.currentTimeMillis(); + IridiumManager.getManager().send(irMsg); + count++; + } + + NeptusLog.pub().warn("Iridium message sent", count + " Iridium messages were sent using " + + IridiumManager.getManager().getCurrentMessenger().getName()); + } + catch (Exception e) { + NeptusLog.pub().warn("Send by Iridium :: " + e.getMessage()); + waiter.deliveryError(message, e); + } + } +} diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java index ded2103b95..fc27bcd7c6 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java @@ -31,22 +31,20 @@ */ package pt.lsts.neptus.comm.manager.imc; -import java.io.IOException; +import java.awt.Component; import java.net.Inet4Address; -import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; import java.time.Duration; import java.time.LocalTime; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; -import java.util.Map; import java.util.Vector; import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -68,24 +66,20 @@ import pt.lsts.imc.AssetReport; import pt.lsts.imc.EntityInfo; import pt.lsts.imc.EntityList; -import pt.lsts.imc.FuelLevel; import pt.lsts.imc.IMCDefinition; import pt.lsts.imc.IMCMessage; import pt.lsts.imc.MessagePart; -import pt.lsts.imc.PlanControlState; -import pt.lsts.imc.PlanControlState.STATE; import pt.lsts.imc.RemoteSensorInfo; import pt.lsts.imc.ReportedState; import pt.lsts.imc.StateReport; import pt.lsts.imc.lsf.LsfMessageLogger; -import pt.lsts.imc.net.IMCFragmentHandler; import pt.lsts.imc.state.ImcSystemState; import pt.lsts.neptus.NeptusLog; import pt.lsts.neptus.comm.CommUtil; import pt.lsts.neptus.comm.IMCSendMessageUtils; import pt.lsts.neptus.comm.IMCUtils; import pt.lsts.neptus.comm.NoTransportAvailableException; -import pt.lsts.neptus.comm.SystemUtils; +import pt.lsts.neptus.comm.admin.CommsAdmin; import pt.lsts.neptus.comm.manager.CommBaseManager; import pt.lsts.neptus.comm.manager.CommManagerStatusChangeListener; import pt.lsts.neptus.comm.manager.MessageFrequencyCalculator; @@ -99,18 +93,11 @@ import pt.lsts.neptus.messages.listener.MessageInfoImpl; import pt.lsts.neptus.messages.listener.MessageListener; import pt.lsts.neptus.plugins.PluginUtils; -import pt.lsts.neptus.systems.external.ExternalSystem; -import pt.lsts.neptus.systems.external.ExternalSystem.ExternalTypeEnum; -import pt.lsts.neptus.systems.external.ExternalSystemsHolder; import pt.lsts.neptus.types.XmlOutputMethods; -import pt.lsts.neptus.types.coord.LocationType; import pt.lsts.neptus.types.vehicle.VehicleType; import pt.lsts.neptus.types.vehicle.VehicleType.SystemTypeEnum; -import pt.lsts.neptus.types.vehicle.VehicleType.VehicleTypeEnum; import pt.lsts.neptus.types.vehicle.VehiclesHolder; -import pt.lsts.neptus.util.AngleUtils; import pt.lsts.neptus.util.GuiUtils; -import pt.lsts.neptus.util.MathMiscUtils; import pt.lsts.neptus.util.NetworkInterfacesUtil; import pt.lsts.neptus.util.NetworkInterfacesUtil.NInterface; import pt.lsts.neptus.util.StringUtils; @@ -161,6 +148,8 @@ public class ImcMsgManager extends private int[] multicastPorts = new int[] { 6969 }; private boolean broadcastEnabled = true; + private CommsAdmin commsAdmin = null; + private ImcMsgManagerAnnounceProcessor announceProcessor; private ImcMsgManagerMessageProcessor messageProcessor; @@ -289,6 +278,12 @@ public void preferencesUpdated() { GeneralPreferences.addPreferencesListener(gplistener); gplistener.preferencesUpdated(); + + commsAdmin = new CommsAdmin(this); + } + + public CommsAdmin getCommsAdmin() { + return commsAdmin; } /* (non-Javadoc) @@ -1175,6 +1170,54 @@ public boolean sendMessage(IMCMessage message, ImcId16 vehicleCommId, String sen return sendMessage(message, vehicleCommId, sendProperties, null); } + /** + * This method is used to send a message to a specific system using new channels. + * Set timeoutMillis to -1 to use the default timeout. + * Leave channelsToSend empty to use the default channels. + * @return Future with the result of the send operation. + */ + public Future sendMessageUsingActiveChannel(IMCMessage message, String destinationName, int timeoutMillis, + Component parentComponentForAlert, + boolean requireUserConfirmOtherThanWifi, + String... channelsToSend) { + + //if (GeneralPreferences.imcUseNewMultiChannelCommsEnable) { + ImcSystem sys = ImcSystemsHolder.lookupSystemByName(destinationName); + if (sys == null) { + return CompletableFuture.completedFuture(SendResult.ERROR); + } + + timeoutMillis = timeoutMillis < 0 ? CommsAdmin.COMM_TIMEOUT_MILLIS : timeoutMillis; + + Future ret = commsAdmin.sendMessage(message, destinationName, timeoutMillis, + parentComponentForAlert, requireUserConfirmOtherThanWifi); + return ret; + } + + public boolean sendMessageUsingActiveChannelWait(IMCMessage message, String destinationName, int timeoutMillis, + Component parentComponentForAlert, + boolean requireUserConfirmOtherThanWifi, + String... channelsToSend) { + Future ret = sendMessageUsingActiveChannel(message, destinationName, timeoutMillis, + parentComponentForAlert, requireUserConfirmOtherThanWifi, channelsToSend); + try { + SendResult sendResult = ret.get(); + switch (sendResult) { + case SUCCESS: + case UNCERTAIN_DELIVERY: + return true; + case ERROR: + case TIMEOUT: + case UNREACHABLE: + default: + return false; + } + } + catch (Exception e) { + return false; + } + } + /** * @param message The message to send * @param systemCommId The id of the destination. diff --git a/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java b/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java index fbddec06ff..57ad9bd1e5 100644 --- a/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java +++ b/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java @@ -132,6 +132,18 @@ public class GeneralPreferences implements PropertiesProvider { " A value too high will create inbound messages delay.") public static int imcReachabilityTestTimeout = 50; + @NeptusProperty(name = "Communication - Send Use New Multi-Channels", category = "IMC Communications", userLevel = LEVEL.ADVANCED, + description = "To use the new multichannel comms. Enable or disable") + public static boolean imcUseNewMultiChannelCommsEnable = false; + + @NeptusProperty(name = "IMC Channels to Use", category = "IMC Communications", userLevel = LEVEL.ADVANCED, + description = "Comma separated transports list. Valid values are (WiFi, Acoustic, GSM, Satellite). (The order implies preference of use.)") + public static String imcChannelsToUse = "WiFi, Acoustic, Satellite"; + + @NeptusProperty(name = "IMC Channel - Max Acoustic Distance (m)", category = "IMC Communications", userLevel = LEVEL.ADVANCED, + description = "The maximum distance in meters to use the acoustic channel.") + public static int imcChannelMaxAcousticDistanceMeters = 2_000; + // ------------------------------------------------------------------------- @NeptusProperty(name = "Logs Downloader - Enable Partial Download", category = "IMC Logs Downloader", userLevel = LEVEL.ADVANCED, From e7d565e0acd331deb5996bc3b3af9a28b92a75db Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 5 Jun 2024 15:04:25 +0100 Subject: [PATCH 06/92] comm/admin/CommsAdmin: Fix sending msg. --- src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java index 16934b2c56..fde40b410b 100644 --- a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java +++ b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java @@ -296,7 +296,7 @@ public ImcMsgManager.SendResult get(long timeout, TimeUnit unit) throws Interrup } break; case IRIDIUM: - sendViaIridium(proxyIridiumSystem.get().getName(), message, waiter); + sendViaIridium(destinationName, message, waiter); return result; case GSM: default: @@ -400,6 +400,7 @@ public void sendViaIridium(String destination, IMCMessage message, ResultWaiter NeptusLog.pub().warn("Iridium message sent", count + " Iridium messages were sent using " + IridiumManager.getManager().getCurrentMessenger().getName()); + waiter.deliverySuccess(message); } catch (Exception e) { NeptusLog.pub().warn("Send by Iridium :: " + e.getMessage()); From 6d9f3a3151c5f6b41f565a89ac860674a7ebd506 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 5 Jun 2024 15:05:47 +0100 Subject: [PATCH 07/92] comm/iridium/ImcIridiumMessage: Reducing max payload for Iridium msgs to account for future RB send. --- src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java b/src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java index c8ff6e0f99..849798559a 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java @@ -47,8 +47,9 @@ public class ImcIridiumMessage extends IridiumMessage { protected IMCMessage msg; - - public static int MaxPayloadSize = 270 - 12; + + // 5 bytes for RB addressing, 6 bytes for type and timestamp, 6 bytes for IMC header + public static int MaxPayloadSize = 270 - 17; public ImcIridiumMessage() { super(2010); From 34049e559d8844aeddc53b00b763247fbfbbe84a Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 5 Jun 2024 18:37:47 +0100 Subject: [PATCH 08/92] plugins/caravelenv/CaravelDataPlotter: First version for Caravel underway data. --- plugins-dev/caravel-env/plugins.lst | 1 + .../caravelenv/CaravelDataPlotter.java | 628 ++++++++++++++++++ 2 files changed, 629 insertions(+) create mode 100644 plugins-dev/caravel-env/plugins.lst create mode 100644 plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java diff --git a/plugins-dev/caravel-env/plugins.lst b/plugins-dev/caravel-env/plugins.lst new file mode 100644 index 0000000000..6298e57ec8 --- /dev/null +++ b/plugins-dev/caravel-env/plugins.lst @@ -0,0 +1 @@ +pt.lsts.neptus.plugins.caravelenv.CaravelDataPlotter diff --git a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java new file mode 100644 index 0000000000..f34511ad0d --- /dev/null +++ b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) + * All rights reserved. + * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal + * + * This file is part of Neptus, Command and Control Framework. + * + * Commercial Licence Usage + * Licencees holding valid commercial Neptus licences may use this file + * in accordance with the commercial licence agreement provided with the + * Software or, alternatively, in accordance with the terms contained in a + * written agreement between you and Universidade do Porto. For licensing + * terms, conditions, and further information contact lsts@fe.up.pt. + * + * Modified European Union Public Licence - EUPL v.1.1 Usage + * Alternatively, this file may be used under the terms of the Modified EUPL, + * Version 1.1 only (the "Licence"), appearing in the file LICENSE.md + * included in the packaging of this file. You may not use this work + * except in compliance with the Licence. Unless required by applicable + * law or agreed to in writing, software distributed under the Licence is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific + * language governing permissions and limitations at + * https://github.com/LSTS/neptus/blob/develop/LICENSE.md + * and http://ec.europa.eu/idabc/eupl.html. + * + * For more information please see . + * + * Author: Paulo Dias + * 5 June 2024 + */ +package pt.lsts.neptus.plugins.caravelenv; + +import com.google.common.eventbus.Subscribe; +import pt.lsts.imc.AirSaturation; +import pt.lsts.imc.Chlorophyll; +import pt.lsts.imc.DissolvedOrganicMatter; +import pt.lsts.imc.DissolvedOxygen; +import pt.lsts.imc.IMCMessage; +import pt.lsts.imc.Salinity; +import pt.lsts.imc.Temperature; +import pt.lsts.imc.Turbidity; +import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.colormap.ColorMap; +import pt.lsts.neptus.colormap.ColorMapFactory; +import pt.lsts.neptus.colormap.ColorMapUtils; +import pt.lsts.neptus.comm.manager.imc.ImcSystem; +import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; +import pt.lsts.neptus.console.ConsoleLayer; +import pt.lsts.neptus.messages.listener.Periodic; +import pt.lsts.neptus.plugins.NeptusProperty; +import pt.lsts.neptus.plugins.PluginDescription; +import pt.lsts.neptus.renderer2d.OffScreenLayerImageControl; +import pt.lsts.neptus.renderer2d.StateRenderer2D; +import pt.lsts.neptus.types.coord.LocationType; +import pt.lsts.neptus.util.conf.PreferencesListener; +import pt.lsts.neptus.util.coord.MapTileRendererCalculator; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.RenderingHints; +import java.awt.Transparency; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author pdias + * + */ +@PluginDescription(name = "Caravel Data Plotter", description = "Plotter for Caravel underway data.") +public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListener { + + @NeptusProperty(name = "Show temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") + public boolean showTemp = false; + @NeptusProperty(name = "Show salinity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Salinity") + public boolean showSal = true; + @NeptusProperty(name = "Show turbidity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Turbidity") + public boolean showTurbidity = false; + @NeptusProperty(name = "Show chlorophyll", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Chlorophyll") + public boolean showChlorophyll = false; + @NeptusProperty(name = "Show dissolved organic matter", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Organic Matter") + public boolean showDissolvedOrganicMatter = false; + @NeptusProperty(name = "Show dissolved oxygen", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Oxygen") + public boolean showDissolvedOxygen = false; + @NeptusProperty(name = "Show air saturation", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") + public boolean showAirSaturation = false; + + @NeptusProperty(name = "Min temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") + private double minTemp = 15; + @NeptusProperty(name = "Max temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") + private double maxTemp = 35; + + @NeptusProperty(name = "Temperature color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") + private ColorMap colormapTemp = ColorMapFactory.createJetColorMap(); + + @NeptusProperty(name = "Min salinity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Salinity") + private double minSal = 33; + @NeptusProperty(name = "Max salinity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Salinity") + private double maxSal = 36; + + @NeptusProperty(name = "Salinity color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Salinity") + private ColorMap colormapSal = ColorMapFactory.createJetColorMap(); + + @NeptusProperty(name = "Min turbidity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Turbidity") + private double minTurbidity = 0; + @NeptusProperty(name = "Max turbidity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Turbidity") + private double maxTurbidity = 30; + + @NeptusProperty(name = "Turbidity color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Turbidity") + private ColorMap colormapTurbidity = ColorMapFactory.createJetColorMap(); + + @NeptusProperty(name = "Min chlorophyll", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Chlorophyll") + private double minChlorophyll = 0; + @NeptusProperty(name = "Max chlorophyll", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Chlorophyll") + private double maxChlorophyll = 2; + + @NeptusProperty(name = "Chlorophyll color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Chlorophyll") + private ColorMap colormapChlorophyll = ColorMapFactory.createJetColorMap(); + + @NeptusProperty(name = "Min dissolved organic matter", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Organic Matter") + private double minDissolvedOrganicMatter = 0; + @NeptusProperty(name = "Max dissolved organic matter", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Organic Matter") + private double maxDissolvedOrganicMatter = 10; + + @NeptusProperty(name = "Dissolved Organic Matter color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Organic Matter") + private ColorMap colormapDissolvedOrganicMatter = ColorMapFactory.createJetColorMap(); + + @NeptusProperty(name = "Min dissolved oxygen", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Oxygen") + private double minDissolvedOxygen = 0; + @NeptusProperty(name = "Max dissolved oxygen", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Oxygen") + private double maxDissolvedOxygen = 300; + + @NeptusProperty(name = "Dissolved Oxygen color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Oxygen") + private ColorMap colormapDissolvedOxygen = ColorMapFactory.createJetColorMap(); + + @NeptusProperty(name = "Min air saturation", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") + private double minAirSaturation = 0; + @NeptusProperty(name = "Max air saturation", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") + private double maxAirSaturation = 100; + + @NeptusProperty(name = "Air Saturation color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") + private ColorMap colormapAirSaturation = ColorMapFactory.createJetColorMap(); + + @NeptusProperty(name = "Max samples", userLevel = NeptusProperty.LEVEL.REGULAR) + private int maxSamples = 35000; + + @NeptusProperty(name = "Clamp to fit", userLevel = NeptusProperty.LEVEL.REGULAR) + private boolean clampToFit = false; + + private OffScreenLayerImageControl offScreenSalinity = new OffScreenLayerImageControl(); + private OffScreenLayerImageControl offScreenTemperature = new OffScreenLayerImageControl(); + private OffScreenLayerImageControl offScreenTurbidity = new OffScreenLayerImageControl(); + private OffScreenLayerImageControl offScreenChlorophyll = new OffScreenLayerImageControl(); + private OffScreenLayerImageControl offScreenDissolvedOrganicMatter = new OffScreenLayerImageControl(); + private OffScreenLayerImageControl offScreenDissolvedOxygen = new OffScreenLayerImageControl(); + private OffScreenLayerImageControl offScreenAirSaturation = new OffScreenLayerImageControl(); + + private Thread painterThread = null; + private AtomicBoolean abortIndicator = null; + + private List pointsTemp = Collections.synchronizedList(new LinkedList<>()); + private List pointsSalinity = Collections.synchronizedList(new LinkedList<>()); + private List pointsTurbidity = Collections.synchronizedList(new LinkedList<>()); + private List pointsChlorophyll = Collections.synchronizedList(new LinkedList<>()); + private List pointsDissolvedOrganicMatter = Collections.synchronizedList(new LinkedList<>()); + private List pointsDissolvedOxygen = Collections.synchronizedList(new LinkedList<>()); + private List pointsAirSaturation = Collections.synchronizedList(new LinkedList<>()); + + private AtomicInteger trigger = new AtomicInteger(0); + private int triggerCount = 0; + + private class DataPoint { + LocationType location = null; + double value = Double.NaN; + } + + private class DataPointXY { + Point2D point = null; + double value = Double.NaN; + } + + /* (non-Javadoc) + * @see pt.lsts.neptus.console.ConsoleLayer#initLayer() + */ + @Override + public void initLayer() { + } + + /* (non-Javadoc) + * @see pt.lsts.neptus.console.ConsoleLayer#cleanLayer() + */ + @Override + public void cleanLayer() { + pointsTemp.clear(); + + } + + /* (non-Javadoc) + * @see pt.lsts.neptus.console.ConsoleLayer#userControlsOpacity() + */ + @Override + public boolean userControlsOpacity() { + return false; + } + +// /* (non-Javadoc) +// * @see pt.lsts.neptus.util.nmea.NmeaListener#nmeaSentence(java.lang.String) +// */ +// @Override +// public void nmeaSentence(String sentence) { +// if (sentence.startsWith("t1")) { +// LocationType loc = MyState.getLocation().getNewAbsoluteLatLonDepth(); +// +// DataPoint pt = new DataPoint(); +// pt.location = loc; +// +// String[] tks = sentence.split(","); +// for (String tk : tks) { +// try { +// String[] tts = tk.trim().split("="); +// if (tts.length < 2) +// continue; +// switch (tts[0].trim()) { +// case "t1": +// pt.temperature = Double.parseDouble(tts[1]); +// break; +// case "s": +// pt.salinity= Double.parseDouble(tts[1]); +// break; +// default: +// break; +// } +// } +// catch (NumberFormatException e) { +// e.printStackTrace(); +// } +// } +// +// try { +// Salinity msgSal = new Salinity(Double.valueOf(pt.salinity).floatValue()); +// msgSal.setSrc(GeneralPreferences.imcCcuId.intValue()); +// msgSal.setTimestampMillis(System.currentTimeMillis()); +// LsfMessageLogger.log(msgSal); +// Temperature msgTemp = new Temperature(Double.valueOf(pt.temperature).floatValue()); +// msgTemp.setSrc(GeneralPreferences.imcCcuId.intValue()); +// msgTemp.setTimestampMillis(System.currentTimeMillis()); +// LsfMessageLogger.log(msgTemp); +// } +// catch (Exception e) { +// e.printStackTrace(); +// } +// +// points.add(pt); +// if (points.size() > maxSamples) +// points.remove(0); +// trigger.incrementAndGet(); +// } +// } + + private LocationType getSystemLocation() { + // TODO FIXME + ImcSystem sys = ImcSystemsHolder.getSystemWithName(getConsole().getMainSystem()); + return sys == null ? null : sys.getLocation(); + } + + private void extractSensorMeasurementValueFromMessage(double value, List points, IMCMessage msg) { + LocationType loc = getSystemLocation(); + DataPoint pt = new DataPoint(); + pt.location = loc; + pt.value = value; + + points.add(pt); + if (points.size() > maxSamples) + points.remove(0); + trigger.incrementAndGet(); + } + + @Subscribe + public void on(Temperature msg) { + extractSensorMeasurementValueFromMessage(msg.getValue(), pointsTemp, msg); + } + + @Subscribe + public void on(Salinity msg) { + extractSensorMeasurementValueFromMessage(msg.getValue(), pointsSalinity, msg); + } + + @Subscribe + public void on(Turbidity msg) { + extractSensorMeasurementValueFromMessage(msg.getValue(), pointsTurbidity, msg); + } + + @Subscribe + public void on(Chlorophyll msg) { + extractSensorMeasurementValueFromMessage(msg.getValue(), pointsChlorophyll, msg); + } + + @Subscribe + public void on(DissolvedOrganicMatter msg) { + extractSensorMeasurementValueFromMessage(msg.getValue(), pointsDissolvedOrganicMatter, msg); + } + + @Subscribe + public void on(DissolvedOxygen msg) { + extractSensorMeasurementValueFromMessage(msg.getValue(), pointsDissolvedOxygen, msg); + } + + @Subscribe + public void on(AirSaturation msg) { + extractSensorMeasurementValueFromMessage(msg.getValue(), pointsAirSaturation, msg); + } + + @Periodic(value = 2_000) + private void update() { + offScreenTemperature.triggerImageRebuild(); + offScreenSalinity.triggerImageRebuild(); + offScreenTurbidity.triggerImageRebuild(); + offScreenChlorophyll.triggerImageRebuild(); + offScreenDissolvedOrganicMatter.triggerImageRebuild(); + offScreenDissolvedOxygen.triggerImageRebuild(); + offScreenAirSaturation.triggerImageRebuild(); + } + + /* (non-Javadoc) + * @see pt.lsts.neptus.console.ConsoleLayer#paint(java.awt.Graphics2D, pt.lsts.neptus.renderer2d.StateRenderer2D) + */ + @Override + public void paint(Graphics2D g, StateRenderer2D renderer) { + super.paint(g, renderer); + + boolean recreateImage = offScreenSalinity.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) + || offScreenTemperature.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) + || offScreenTurbidity.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) + || offScreenChlorophyll.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) + || offScreenDissolvedOrganicMatter.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) + || offScreenDissolvedOxygen.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) + || offScreenAirSaturation.paintPhaseStartTestRecreateImageAndRecreate(g, renderer); + + int c = trigger.get(); + if (c != triggerCount) { + recreateImage = true; + triggerCount = c; + } + + if (recreateImage) { + if (painterThread != null) { + try { + abortIndicator.set(true); + painterThread.interrupt(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + final MapTileRendererCalculator rendererCalculator = new MapTileRendererCalculator(renderer); + abortIndicator = new AtomicBoolean(); + painterThread = new Thread(new Runnable() { + @Override + public void run() { + Graphics2D g2 = offScreenSalinity.getImageGraphics(); + try { + + ArrayList ptsTemp = new ArrayList<>(); + ArrayList ptsSalinity = new ArrayList<>(); + ArrayList ptsTurbidity = new ArrayList<>(); + ArrayList ptsChlorophyll = new ArrayList<>(); + ArrayList ptsDissolvedOrganicMatter = new ArrayList<>(); + ArrayList ptsDissolvedOxygen = new ArrayList<>(); + ArrayList ptsAirSaturation = new ArrayList<>(); + + if (showTemp) { + ptsTemp = transformDataPointsToXY(pointsTemp, rendererCalculator); + } + if (showSal) { + ptsSalinity = transformDataPointsToXY(pointsSalinity, rendererCalculator); + } + if (showTurbidity) { + ptsTurbidity = transformDataPointsToXY(pointsTurbidity, rendererCalculator); + } + if (showChlorophyll) { + ptsChlorophyll = transformDataPointsToXY(pointsChlorophyll, rendererCalculator); + } + if (showDissolvedOrganicMatter) { + ptsDissolvedOrganicMatter = transformDataPointsToXY(pointsDissolvedOrganicMatter, rendererCalculator); + } + if (showDissolvedOxygen) { + ptsDissolvedOxygen = transformDataPointsToXY(pointsDissolvedOxygen, rendererCalculator); + } + if (showAirSaturation) { + ptsAirSaturation = transformDataPointsToXY(pointsAirSaturation, rendererCalculator); + } + + if (showTemp && !abortIndicator.get()) { + try { + recreateSensorDataCacheImage(ptsTemp, colormapTemp, minTemp, maxTemp, offScreenTemperature, g2, rendererCalculator); + } + catch (Exception e) { + e.printStackTrace(); + offScreenTemperature.triggerImageRebuild(); + } + } + + if (showSal && !abortIndicator.get()) { + try { + recreateSensorDataCacheImage(ptsSalinity, colormapSal, minSal, maxSal, offScreenSalinity, g2, rendererCalculator); + } + catch (Exception e) { + e.printStackTrace(); + offScreenSalinity.triggerImageRebuild(); + } + } + + if (showTurbidity && !abortIndicator.get()) { + try { + recreateSensorDataCacheImage(ptsTurbidity, colormapTurbidity, minTurbidity, maxTurbidity, offScreenTurbidity, g2, rendererCalculator); + } + catch (Exception e) { + e.printStackTrace(); + offScreenTurbidity.triggerImageRebuild(); + } + } + + if (showChlorophyll && !abortIndicator.get()) { + try { + recreateSensorDataCacheImage(ptsChlorophyll, colormapChlorophyll, minChlorophyll, maxChlorophyll, offScreenChlorophyll, g2, rendererCalculator); + } + catch (Exception e) { + e.printStackTrace(); + offScreenChlorophyll.triggerImageRebuild(); + } + } + + if (showDissolvedOrganicMatter && !abortIndicator.get()) { + try { + recreateSensorDataCacheImage(ptsDissolvedOrganicMatter, colormapDissolvedOrganicMatter, minDissolvedOrganicMatter, maxDissolvedOrganicMatter, offScreenDissolvedOrganicMatter, g2, rendererCalculator); + } + catch (Exception e) { + e.printStackTrace(); + offScreenDissolvedOrganicMatter.triggerImageRebuild(); + } + } + + if (showDissolvedOxygen && !abortIndicator.get()) { + try { + recreateSensorDataCacheImage(ptsDissolvedOxygen, colormapDissolvedOxygen, minDissolvedOxygen, maxDissolvedOxygen, offScreenDissolvedOxygen, g2, rendererCalculator); + } + catch (Exception e) { + e.printStackTrace(); + offScreenDissolvedOxygen.triggerImageRebuild(); + } + } + + if (showAirSaturation && !abortIndicator.get()) { + try { + recreateSensorDataCacheImage(ptsAirSaturation, colormapAirSaturation, minAirSaturation, maxAirSaturation, offScreenAirSaturation, g2, rendererCalculator); + } + catch (Exception e) { + e.printStackTrace(); + offScreenAirSaturation.triggerImageRebuild(); + } + } + + g2.dispose(); + } + catch (Exception | Error e) { + e.printStackTrace(); + offScreenTemperature.triggerImageRebuild(); + offScreenSalinity.triggerImageRebuild(); + offScreenTurbidity.triggerImageRebuild(); + offScreenChlorophyll.triggerImageRebuild(); + offScreenDissolvedOrganicMatter.triggerImageRebuild(); + offScreenDissolvedOxygen.triggerImageRebuild(); + offScreenAirSaturation.triggerImageRebuild(); + } + + renderer.invalidate(); + renderer.repaint(200); + } + }, CaravelDataPlotter.class.getSimpleName() + ":: Painter"); + painterThread.setDaemon(true); + painterThread.start(); + } + offScreenTemperature.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); + offScreenSalinity.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); + offScreenTurbidity.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); + offScreenChlorophyll.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); + offScreenDissolvedOrganicMatter.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); + offScreenDissolvedOxygen.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); + offScreenAirSaturation.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); + + paintColorbars(g, renderer); + } + + private void recreateSensorDataCacheImage(ArrayList pts, ColorMap colormap, double minVal, + double maxVal, OffScreenLayerImageControl offScreenImageControl, Graphics2D g2, + MapTileRendererCalculator rendererCalculator) { + double fullImgWidth = rendererCalculator.getSize().getWidth() + offScreenImageControl.getOffScreenBufferPixel() * 2.; + double fullImgHeight = rendererCalculator.getSize().getHeight() + offScreenImageControl.getOffScreenBufferPixel() * 2.; + + double xMin = fullImgWidth; + double yMin = fullImgHeight; + xMin = 8; + yMin = 8; + + double cacheImgScaleX = 1. / xMin; + double cacheImgScaleY = 1. / yMin; + + double cacheImgWidth = fullImgWidth; + double cacheImgHeight = fullImgHeight; + cacheImgWidth *= cacheImgScaleX; + cacheImgHeight *= cacheImgScaleY; + + BufferedImage cacheImg = createBufferedImage((int) cacheImgWidth, (int) cacheImgHeight, Transparency.TRANSLUCENT); + pts.parallelStream().forEach(pt -> { + try { + if (abortIndicator.get()) + return; + + double v = (double) pt.value; + + if (clampToFit + && (Double.compare(v, minVal) < 0 || Double.compare(v, maxVal) > 0)) + return; + + Color color = colormap.getColor(ColorMapUtils.getColorIndexZeroToOneLog10(v, minVal, maxVal)); + cacheImg.setRGB((int) ((pt.point.getX() + offScreenImageControl.getOffScreenBufferPixel()) * cacheImgScaleX), + (int) ((pt.point.getY() + offScreenImageControl.getOffScreenBufferPixel()) * cacheImgScaleY), color.getRGB()); + } + catch (Exception e) { + NeptusLog.pub().trace(e); + } + }); + + Graphics2D gt = (Graphics2D) g2.create(); + try { + gt.translate(rendererCalculator.getWidth() / 2., rendererCalculator.getHeight() / 2.); + gt.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT); + gt.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_DEFAULT); + gt.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + gt.drawImage(cacheImg, -(int) (cacheImg.getWidth() / cacheImgScaleX / 2.), + -(int) (cacheImg.getHeight() / cacheImgScaleY / 2.), + (int) (cacheImg.getWidth() / cacheImgScaleX), + (int) (cacheImg.getHeight() / cacheImgScaleY), null, null); + } + catch (Exception e) { + NeptusLog.pub().trace(e); + } + if (gt != null) + gt.dispose(); + } + + private ArrayList transformDataPointsToXY(List points, MapTileRendererCalculator rendererCalculator) { + return pointsTemp.stream().collect(ArrayList::new, + (r, p) -> { + if (abortIndicator.get()) { + return; + } + Point2D pxy = rendererCalculator.getScreenPosition(p.location); + DataPointXY dpxy = new DataPointXY(); + dpxy.point = pxy; + dpxy.value = p.value; + r.add(dpxy); + }, (r1, r2) -> { + for (DataPointXY d2 : r2) { + if (abortIndicator.get()) { + break; + } + boolean found = false; + for (DataPointXY d1 : r1) { + if (abortIndicator.get()) { + break; + } + if (d2.point.equals(d1.point)) { + d1.value = (d1.value + d2.value) / 2.; + found = true; + break; + } + } + if (!found) { + r1.add(d2); + } + } + }); + } + + private static BufferedImage createBufferedImage(int cacheImgWidth, int cacheImgHeight, int translucent) { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice gs = ge.getDefaultScreenDevice(); + GraphicsConfiguration gc = gs.getDefaultConfiguration(); + return gc.createCompatibleImage((int) cacheImgWidth , (int) cacheImgHeight , Transparency.TRANSLUCENT); + } + + /** + * @param go + * @param renderer + */ + private void paintColorbars(Graphics2D go, StateRenderer2D renderer) { +// int offsetHeight = 130; +// int offsetWidth = 5; +// int offsetDelta = 130; +// if (showSal) { +// Graphics2D gl = (Graphics2D) go.create(); +// gl.translate(offsetWidth, offsetHeight); +// ColorBarPainterUtil.paintColorBar(gl, colorMapVar, I18n.text(info.name), info.unit, minValue, maxValue); +// gl.dispose(); +// offsetHeight += offsetDelta; +// } + } + + /* (non-Javadoc) + * @see pt.lsts.neptus.util.conf.PreferencesListener#preferencesUpdated() + */ + @Override + public void preferencesUpdated() { + getConsole().repaint(); + } +} \ No newline at end of file From 3d377bc49da62dd352b01b546f81b3d1c3159e12 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 6 Jun 2024 14:54:21 +0100 Subject: [PATCH 09/92] plugins/caravelenv/CaravelDataPlotter: Paint fixes. --- .../caravelenv/CaravelDataPlotter.java | 87 +++++++++++-------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java index f34511ad0d..7be913079e 100644 --- a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java +++ b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java @@ -96,66 +96,66 @@ public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListe public boolean showAirSaturation = false; @NeptusProperty(name = "Min temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") - private double minTemp = 15; + public double minTemp = 15; @NeptusProperty(name = "Max temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") - private double maxTemp = 35; + public double maxTemp = 35; @NeptusProperty(name = "Temperature color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") - private ColorMap colormapTemp = ColorMapFactory.createJetColorMap(); + public ColorMap colormapTemp = ColorMapFactory.createJetColorMap(); @NeptusProperty(name = "Min salinity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Salinity") - private double minSal = 33; + public double minSal = 33; @NeptusProperty(name = "Max salinity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Salinity") - private double maxSal = 36; + public double maxSal = 36; @NeptusProperty(name = "Salinity color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Salinity") - private ColorMap colormapSal = ColorMapFactory.createJetColorMap(); + public ColorMap colormapSal = ColorMapFactory.createJetColorMap(); @NeptusProperty(name = "Min turbidity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Turbidity") - private double minTurbidity = 0; + public double minTurbidity = 0; @NeptusProperty(name = "Max turbidity", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Turbidity") - private double maxTurbidity = 30; + public double maxTurbidity = 30; @NeptusProperty(name = "Turbidity color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Turbidity") - private ColorMap colormapTurbidity = ColorMapFactory.createJetColorMap(); + public ColorMap colormapTurbidity = ColorMapFactory.createJetColorMap(); @NeptusProperty(name = "Min chlorophyll", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Chlorophyll") - private double minChlorophyll = 0; + public double minChlorophyll = 0; @NeptusProperty(name = "Max chlorophyll", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Chlorophyll") - private double maxChlorophyll = 2; + public double maxChlorophyll = 2; @NeptusProperty(name = "Chlorophyll color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Chlorophyll") - private ColorMap colormapChlorophyll = ColorMapFactory.createJetColorMap(); + public ColorMap colormapChlorophyll = ColorMapFactory.createJetColorMap(); @NeptusProperty(name = "Min dissolved organic matter", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Organic Matter") - private double minDissolvedOrganicMatter = 0; + public double minDissolvedOrganicMatter = 0; @NeptusProperty(name = "Max dissolved organic matter", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Organic Matter") - private double maxDissolvedOrganicMatter = 10; + public double maxDissolvedOrganicMatter = 10; @NeptusProperty(name = "Dissolved Organic Matter color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Organic Matter") - private ColorMap colormapDissolvedOrganicMatter = ColorMapFactory.createJetColorMap(); + public ColorMap colormapDissolvedOrganicMatter = ColorMapFactory.createJetColorMap(); @NeptusProperty(name = "Min dissolved oxygen", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Oxygen") - private double minDissolvedOxygen = 0; + public double minDissolvedOxygen = 0; @NeptusProperty(name = "Max dissolved oxygen", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Oxygen") - private double maxDissolvedOxygen = 300; + public double maxDissolvedOxygen = 300; @NeptusProperty(name = "Dissolved Oxygen color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Oxygen") - private ColorMap colormapDissolvedOxygen = ColorMapFactory.createJetColorMap(); + public ColorMap colormapDissolvedOxygen = ColorMapFactory.createJetColorMap(); @NeptusProperty(name = "Min air saturation", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") - private double minAirSaturation = 0; + public double minAirSaturation = 0; @NeptusProperty(name = "Max air saturation", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") - private double maxAirSaturation = 100; + public double maxAirSaturation = 100; @NeptusProperty(name = "Air Saturation color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") - private ColorMap colormapAirSaturation = ColorMapFactory.createJetColorMap(); + public ColorMap colormapAirSaturation = ColorMapFactory.createJetColorMap(); @NeptusProperty(name = "Max samples", userLevel = NeptusProperty.LEVEL.REGULAR) - private int maxSamples = 35000; + public int maxSamples = 35000; @NeptusProperty(name = "Clamp to fit", userLevel = NeptusProperty.LEVEL.REGULAR) - private boolean clampToFit = false; + public boolean clampToFit = false; private OffScreenLayerImageControl offScreenSalinity = new OffScreenLayerImageControl(); private OffScreenLayerImageControl offScreenTemperature = new OffScreenLayerImageControl(); @@ -288,36 +288,43 @@ private void extractSensorMeasurementValueFromMessage(double value, List ptsTemp = new ArrayList<>(); ArrayList ptsSalinity = new ArrayList<>(); ArrayList ptsTurbidity = new ArrayList<>(); @@ -403,7 +416,7 @@ public void run() { if (showTemp && !abortIndicator.get()) { try { - recreateSensorDataCacheImage(ptsTemp, colormapTemp, minTemp, maxTemp, offScreenTemperature, g2, rendererCalculator); + recreateSensorDataCacheImage(ptsTemp, colormapTemp, minTemp, maxTemp, offScreenTemperature, g2Temp, rendererCalculator); } catch (Exception e) { e.printStackTrace(); @@ -413,7 +426,7 @@ public void run() { if (showSal && !abortIndicator.get()) { try { - recreateSensorDataCacheImage(ptsSalinity, colormapSal, minSal, maxSal, offScreenSalinity, g2, rendererCalculator); + recreateSensorDataCacheImage(ptsSalinity, colormapSal, minSal, maxSal, offScreenSalinity, g2Salinity, rendererCalculator); } catch (Exception e) { e.printStackTrace(); @@ -423,7 +436,7 @@ public void run() { if (showTurbidity && !abortIndicator.get()) { try { - recreateSensorDataCacheImage(ptsTurbidity, colormapTurbidity, minTurbidity, maxTurbidity, offScreenTurbidity, g2, rendererCalculator); + recreateSensorDataCacheImage(ptsTurbidity, colormapTurbidity, minTurbidity, maxTurbidity, offScreenTurbidity, g2Turbidity, rendererCalculator); } catch (Exception e) { e.printStackTrace(); @@ -433,7 +446,7 @@ public void run() { if (showChlorophyll && !abortIndicator.get()) { try { - recreateSensorDataCacheImage(ptsChlorophyll, colormapChlorophyll, minChlorophyll, maxChlorophyll, offScreenChlorophyll, g2, rendererCalculator); + recreateSensorDataCacheImage(ptsChlorophyll, colormapChlorophyll, minChlorophyll, maxChlorophyll, offScreenChlorophyll, g2Chlorophyll, rendererCalculator); } catch (Exception e) { e.printStackTrace(); @@ -443,7 +456,7 @@ public void run() { if (showDissolvedOrganicMatter && !abortIndicator.get()) { try { - recreateSensorDataCacheImage(ptsDissolvedOrganicMatter, colormapDissolvedOrganicMatter, minDissolvedOrganicMatter, maxDissolvedOrganicMatter, offScreenDissolvedOrganicMatter, g2, rendererCalculator); + recreateSensorDataCacheImage(ptsDissolvedOrganicMatter, colormapDissolvedOrganicMatter, minDissolvedOrganicMatter, maxDissolvedOrganicMatter, offScreenDissolvedOrganicMatter, g2DissolvedOrganicMatter, rendererCalculator); } catch (Exception e) { e.printStackTrace(); @@ -453,7 +466,7 @@ public void run() { if (showDissolvedOxygen && !abortIndicator.get()) { try { - recreateSensorDataCacheImage(ptsDissolvedOxygen, colormapDissolvedOxygen, minDissolvedOxygen, maxDissolvedOxygen, offScreenDissolvedOxygen, g2, rendererCalculator); + recreateSensorDataCacheImage(ptsDissolvedOxygen, colormapDissolvedOxygen, minDissolvedOxygen, maxDissolvedOxygen, offScreenDissolvedOxygen, g2DissolvedOxygen, rendererCalculator); } catch (Exception e) { e.printStackTrace(); @@ -463,7 +476,7 @@ public void run() { if (showAirSaturation && !abortIndicator.get()) { try { - recreateSensorDataCacheImage(ptsAirSaturation, colormapAirSaturation, minAirSaturation, maxAirSaturation, offScreenAirSaturation, g2, rendererCalculator); + recreateSensorDataCacheImage(ptsAirSaturation, colormapAirSaturation, minAirSaturation, maxAirSaturation, offScreenAirSaturation, g2AirSaturation, rendererCalculator); } catch (Exception e) { e.printStackTrace(); @@ -471,7 +484,13 @@ public void run() { } } - g2.dispose(); + g2Temp.dispose(); + g2Salinity.dispose(); + g2Turbidity.dispose(); + g2Chlorophyll.dispose(); + g2DissolvedOrganicMatter.dispose(); + g2DissolvedOxygen.dispose(); + g2AirSaturation.dispose(); } catch (Exception | Error e) { e.printStackTrace(); @@ -561,7 +580,7 @@ private void recreateSensorDataCacheImage(ArrayList pts, ColorMap c } private ArrayList transformDataPointsToXY(List points, MapTileRendererCalculator rendererCalculator) { - return pointsTemp.stream().collect(ArrayList::new, + return points.stream().collect(ArrayList::new, (r, p) -> { if (abortIndicator.get()) { return; From 0a8072d24864519f3d041d2519e5533938b46b09 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 14 Jun 2024 16:58:48 +0100 Subject: [PATCH 10/92] plugins/caravelenv/CaravelDataPlotter: More paint work, currents in WIP. --- .../caravelenv/CaravelDataPlotter.java | 436 +++++++++++++++--- 1 file changed, 374 insertions(+), 62 deletions(-) diff --git a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java index 7be913079e..fba8d274f9 100644 --- a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java +++ b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java @@ -33,8 +33,11 @@ package pt.lsts.neptus.plugins.caravelenv; import com.google.common.eventbus.Subscribe; +import org.apache.commons.lang3.tuple.Triple; import pt.lsts.imc.AirSaturation; import pt.lsts.imc.Chlorophyll; +import pt.lsts.imc.CurrentProfile; +import pt.lsts.imc.CurrentProfileCell; import pt.lsts.imc.DissolvedOrganicMatter; import pt.lsts.imc.DissolvedOxygen; import pt.lsts.imc.IMCMessage; @@ -42,43 +45,66 @@ import pt.lsts.imc.Temperature; import pt.lsts.imc.Turbidity; import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.colormap.ColorBarPainterUtil; import pt.lsts.neptus.colormap.ColorMap; import pt.lsts.neptus.colormap.ColorMapFactory; import pt.lsts.neptus.colormap.ColorMapUtils; import pt.lsts.neptus.comm.manager.imc.ImcSystem; import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; import pt.lsts.neptus.console.ConsoleLayer; +import pt.lsts.neptus.console.plugins.MainVehicleChangeListener; import pt.lsts.neptus.messages.listener.Periodic; import pt.lsts.neptus.plugins.NeptusProperty; import pt.lsts.neptus.plugins.PluginDescription; import pt.lsts.neptus.renderer2d.OffScreenLayerImageControl; import pt.lsts.neptus.renderer2d.StateRenderer2D; import pt.lsts.neptus.types.coord.LocationType; +import pt.lsts.neptus.util.AngleUtils; import pt.lsts.neptus.util.conf.PreferencesListener; import pt.lsts.neptus.util.coord.MapTileRendererCalculator; +import scala.runtime.StringFormat; import java.awt.Color; +import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.RenderingHints; import java.awt.Transparency; +import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Vector; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +import static com.sun.tools.doclint.Entity.gt; /** * @author pdias * */ @PluginDescription(name = "Caravel Data Plotter", description = "Plotter for Caravel underway data.") -public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListener { +public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListener, MainVehicleChangeListener { + + final static int ARROW_RADIUS = 12; + final static Path2D.Double arrow = new Path2D.Double(); + static { + arrow.moveTo(-5, 6); + arrow.lineTo(0, -6); + arrow.lineTo(5, 6); + arrow.lineTo(0, 3); + arrow.lineTo(-5, 6); + arrow.closePath(); + } @NeptusProperty(name = "Show temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") public boolean showTemp = false; @@ -94,6 +120,8 @@ public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListe public boolean showDissolvedOxygen = false; @NeptusProperty(name = "Show air saturation", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") public boolean showAirSaturation = false; + @NeptusProperty(name = "Show water current", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Water Current") + public boolean showWaterCurrent = false; @NeptusProperty(name = "Min temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") public double minTemp = 15; @@ -151,6 +179,20 @@ public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListe @NeptusProperty(name = "Air Saturation color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") public ColorMap colormapAirSaturation = ColorMapFactory.createJetColorMap(); + @NeptusProperty(name = "Min water current", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Water Current") + public double minWaterCurrent = -2; + @NeptusProperty(name = "Max water current", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Water Current") + public double maxWaterCurrent = 2; + + @NeptusProperty(name = "Water Current color map", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Water Current") + public ColorMap colormapWaterCurrent = ColorMapFactory.createJetColorMap(); + @NeptusProperty(name = "Water Current Depth", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Water Current", + description = "The layer to show the water current data (m).") + public double waterCurrentDepth = 2.0; + @NeptusProperty(name = "Water Current Depth Window (m)", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Water Current", + description = "Window is +- this value from the waterCurrentDepth.") + public short waterCurrentDepthWindow = 2; + @NeptusProperty(name = "Max samples", userLevel = NeptusProperty.LEVEL.REGULAR) public int maxSamples = 35000; @@ -164,6 +206,7 @@ public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListe private OffScreenLayerImageControl offScreenDissolvedOrganicMatter = new OffScreenLayerImageControl(); private OffScreenLayerImageControl offScreenDissolvedOxygen = new OffScreenLayerImageControl(); private OffScreenLayerImageControl offScreenAirSaturation = new OffScreenLayerImageControl(); + private OffScreenLayerImageControl offScreenWaterCurrent = new OffScreenLayerImageControl(); private Thread painterThread = null; private AtomicBoolean abortIndicator = null; @@ -175,20 +218,43 @@ public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListe private List pointsDissolvedOrganicMatter = Collections.synchronizedList(new LinkedList<>()); private List pointsDissolvedOxygen = Collections.synchronizedList(new LinkedList<>()); private List pointsAirSaturation = Collections.synchronizedList(new LinkedList<>()); + private List pointsWaterCurrent = Collections.synchronizedList(new LinkedList<>()); private AtomicInteger trigger = new AtomicInteger(0); private int triggerCount = 0; - private class DataPoint { + @Override + public void mainVehicleChange(String id) { + pointsTemp.clear(); + pointsSalinity.clear(); + pointsTurbidity.clear(); + pointsChlorophyll.clear(); + pointsDissolvedOrganicMatter.clear(); + pointsDissolvedOxygen.clear(); + pointsAirSaturation.clear(); + pointsWaterCurrent.clear(); + } + + private static class DataPoint { LocationType location = null; double value = Double.NaN; } - private class DataPointXY { + private static class DataPointPolar extends DataPoint { + double directionRads = Double.NaN; + double zDown = Double.NaN; + } + + private static class DataPointXY { Point2D point = null; double value = Double.NaN; } + private static class DataPointXYPolar extends DataPointXY { + double directionRads = Double.NaN; + double zDown = Double.NaN; + } + /* (non-Javadoc) * @see pt.lsts.neptus.console.ConsoleLayer#initLayer() */ @@ -273,6 +339,12 @@ private LocationType getSystemLocation() { return sys == null ? null : sys.getLocation(); } + private double getSystemLocationDepth() { + // TODO FIXME + ImcSystem sys = ImcSystemsHolder.getSystemWithName(getConsole().getMainSystem()); + return sys == null ? Double.NaN : sys.getLocation().getDepth(); + } + private void extractSensorMeasurementValueFromMessage(double value, List points, IMCMessage msg) { LocationType loc = getSystemLocation(); DataPoint pt = new DataPoint(); @@ -287,55 +359,144 @@ private void extractSensorMeasurementValueFromMessage(double value, List profile = msg.getProfile(); + for (int i = 0; i < profile.size(); i++) { + CurrentProfileCell cpcell = profile.get(i); + List points = pointsWaterCurrent; + + double measureDepth = cpcell.getCellPosition() + (depth < 0 ? 0 : depth); + + DataPointPolar pt = new DataPointPolar(); + pt.location = loc; + Triple valueSDQ = calcWaterSpeedAndDirectionFromBeams(nBeams, cpcell); + if (!Double.isNaN(valueSDQ.getLeft()) && !Double.isNaN(valueSDQ.getMiddle()) && !Double.isNaN(valueSDQ.getRight())) { + pt.value = valueSDQ.getLeft(); + pt.directionRads = valueSDQ.getMiddle(); + pt.zDown = measureDepth; + points.add(pt); + } + } + + if (pointsWaterCurrent.size() > maxSamples) + pointsWaterCurrent.remove(0); + trigger.incrementAndGet(); + } + + private Triple calcWaterSpeedAndDirectionFromBeams(short nBeams, CurrentProfileCell cpcell) { + double vel = Double.NaN; + double dirRads = Double.NaN; + double z = Double.NaN; + + if (nBeams == 3 || nBeams == 4) { + vel = Math.sqrt(Math.pow(cpcell.getBeams().get(0).getVel(), 2) + Math.pow(cpcell.getBeams().get(1).getVel(), 2)); + // East, North + dirRads = AngleUtils.nomalizeAngleRads2Pi(AngleUtils.calcAngle(0, 0, cpcell.getBeams().get(0).getVel(), cpcell.getBeams().get(1).getVel())); + // Up to Down + z = -1 * cpcell.getBeams().get(2).getVel(); + } + if (nBeams == 4) { + z = -1 * (cpcell.getBeams().get(2).getVel() + cpcell.getBeams().get(3).getVel()) / 2.0; + } + return Triple.of(vel, dirRads, z); + } + @Periodic(value = 2_000) private void update() { - offScreenTemperature.triggerImageRebuild(); - offScreenSalinity.triggerImageRebuild(); - offScreenTurbidity.triggerImageRebuild(); - offScreenChlorophyll.triggerImageRebuild(); - offScreenDissolvedOrganicMatter.triggerImageRebuild(); - offScreenDissolvedOxygen.triggerImageRebuild(); - offScreenAirSaturation.triggerImageRebuild(); + triggerAllImagesRebuild(); } /* (non-Javadoc) @@ -345,13 +506,15 @@ private void update() { public void paint(Graphics2D g, StateRenderer2D renderer) { super.paint(g, renderer); - boolean recreateImage = offScreenSalinity.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) - || offScreenTemperature.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) - || offScreenTurbidity.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) - || offScreenChlorophyll.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) - || offScreenDissolvedOrganicMatter.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) - || offScreenDissolvedOxygen.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) - || offScreenAirSaturation.paintPhaseStartTestRecreateImageAndRecreate(g, renderer); + // Wee need all tests to run to recreate the image cache and not just the first one that is true + boolean recreateImage = offScreenSalinity.paintPhaseStartTestRecreateImageAndRecreate(g, renderer); + recreateImage = offScreenTemperature.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) || recreateImage; + recreateImage = offScreenTurbidity.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) || recreateImage; + recreateImage = offScreenChlorophyll.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) || recreateImage; + recreateImage = offScreenDissolvedOrganicMatter.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) || recreateImage; + recreateImage = offScreenDissolvedOxygen.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) || recreateImage; + recreateImage = offScreenAirSaturation.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) || recreateImage; + recreateImage = offScreenWaterCurrent.paintPhaseStartTestRecreateImageAndRecreate(g, renderer) || recreateImage; int c = trigger.get(); if (c != triggerCount) { @@ -382,15 +545,17 @@ public void run() { Graphics2D g2DissolvedOrganicMatter = offScreenDissolvedOrganicMatter.getImageGraphics(); Graphics2D g2DissolvedOxygen = offScreenDissolvedOxygen.getImageGraphics(); Graphics2D g2AirSaturation = offScreenAirSaturation.getImageGraphics(); + Graphics2D g2WaterCurrent = offScreenWaterCurrent.getImageGraphics(); try { - ArrayList ptsTemp = new ArrayList<>(); - ArrayList ptsSalinity = new ArrayList<>(); - ArrayList ptsTurbidity = new ArrayList<>(); - ArrayList ptsChlorophyll = new ArrayList<>(); - ArrayList ptsDissolvedOrganicMatter = new ArrayList<>(); - ArrayList ptsDissolvedOxygen = new ArrayList<>(); - ArrayList ptsAirSaturation = new ArrayList<>(); + List ptsTemp = new ArrayList<>(); + List ptsSalinity = new ArrayList<>(); + List ptsTurbidity = new ArrayList<>(); + List ptsChlorophyll = new ArrayList<>(); + List ptsDissolvedOrganicMatter = new ArrayList<>(); + List ptsDissolvedOxygen = new ArrayList<>(); + List ptsAirSaturation = new ArrayList<>(); + List ptsWaterCurrent = new ArrayList<>(); if (showTemp) { ptsTemp = transformDataPointsToXY(pointsTemp, rendererCalculator); @@ -413,6 +578,9 @@ public void run() { if (showAirSaturation) { ptsAirSaturation = transformDataPointsToXY(pointsAirSaturation, rendererCalculator); } + if (showWaterCurrent) { + ptsWaterCurrent = transformCurrentDataPointsToXYPolar(pointsWaterCurrent, waterCurrentDepth, waterCurrentDepthWindow, rendererCalculator); + } if (showTemp && !abortIndicator.get()) { try { @@ -484,6 +652,17 @@ public void run() { } } + if (showWaterCurrent && !abortIndicator.get()) { + try { + recreateSensorDataCacheImage(Collections.unmodifiableList(ptsWaterCurrent), colormapWaterCurrent, minWaterCurrent, + maxWaterCurrent, offScreenWaterCurrent, g2WaterCurrent, rendererCalculator); + } + catch (Exception e) { + e.printStackTrace(); + offScreenWaterCurrent.triggerImageRebuild(); + } + } + g2Temp.dispose(); g2Salinity.dispose(); g2Turbidity.dispose(); @@ -491,16 +670,11 @@ public void run() { g2DissolvedOrganicMatter.dispose(); g2DissolvedOxygen.dispose(); g2AirSaturation.dispose(); + g2WaterCurrent.dispose(); } catch (Exception | Error e) { e.printStackTrace(); - offScreenTemperature.triggerImageRebuild(); - offScreenSalinity.triggerImageRebuild(); - offScreenTurbidity.triggerImageRebuild(); - offScreenChlorophyll.triggerImageRebuild(); - offScreenDissolvedOrganicMatter.triggerImageRebuild(); - offScreenDissolvedOxygen.triggerImageRebuild(); - offScreenAirSaturation.triggerImageRebuild(); + triggerAllImagesRebuild(); } renderer.invalidate(); @@ -517,11 +691,23 @@ public void run() { offScreenDissolvedOrganicMatter.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); offScreenDissolvedOxygen.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); offScreenAirSaturation.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); + offScreenWaterCurrent.paintPhaseEndFinishImageRecreateAndPaintImageCacheToRendererNoGraphicDispose(g, renderer); paintColorbars(g, renderer); } - private void recreateSensorDataCacheImage(ArrayList pts, ColorMap colormap, double minVal, + private void triggerAllImagesRebuild() { + offScreenTemperature.triggerImageRebuild(); + offScreenSalinity.triggerImageRebuild(); + offScreenTurbidity.triggerImageRebuild(); + offScreenChlorophyll.triggerImageRebuild(); + offScreenDissolvedOrganicMatter.triggerImageRebuild(); + offScreenDissolvedOxygen.triggerImageRebuild(); + offScreenAirSaturation.triggerImageRebuild(); + offScreenWaterCurrent.triggerImageRebuild(); + } + + private void recreateSensorDataCacheImage(List pts, ColorMap colormap, double minVal, double maxVal, OffScreenLayerImageControl offScreenImageControl, Graphics2D g2, MapTileRendererCalculator rendererCalculator) { double fullImgWidth = rendererCalculator.getSize().getWidth() + offScreenImageControl.getOffScreenBufferPixel() * 2.; @@ -541,25 +727,15 @@ private void recreateSensorDataCacheImage(ArrayList pts, ColorMap c cacheImgHeight *= cacheImgScaleY; BufferedImage cacheImg = createBufferedImage((int) cacheImgWidth, (int) cacheImgHeight, Transparency.TRANSLUCENT); - pts.parallelStream().forEach(pt -> { - try { - if (abortIndicator.get()) - return; - - double v = (double) pt.value; - - if (clampToFit - && (Double.compare(v, minVal) < 0 || Double.compare(v, maxVal) > 0)) - return; - - Color color = colormap.getColor(ColorMapUtils.getColorIndexZeroToOneLog10(v, minVal, maxVal)); - cacheImg.setRGB((int) ((pt.point.getX() + offScreenImageControl.getOffScreenBufferPixel()) * cacheImgScaleX), - (int) ((pt.point.getY() + offScreenImageControl.getOffScreenBufferPixel()) * cacheImgScaleY), color.getRGB()); + boolean useArrows = false; + if (!pts.isEmpty()) { + DataPointXY pt0 = pts.get(0); + if (pt0 instanceof DataPointXYPolar) { + useArrows = true; } - catch (Exception e) { - NeptusLog.pub().trace(e); - } - }); + } + pts.parallelStream().forEach(getDataPointXYSensorPainter(colormap, minVal, maxVal, offScreenImageControl, + cacheImg, cacheImgScaleX, cacheImgScaleY, rendererCalculator, useArrows)); Graphics2D gt = (Graphics2D) g2.create(); try { @@ -579,7 +755,48 @@ private void recreateSensorDataCacheImage(ArrayList pts, ColorMap c gt.dispose(); } - private ArrayList transformDataPointsToXY(List points, MapTileRendererCalculator rendererCalculator) { + private Consumer getDataPointXYSensorPainter(ColorMap colormap, double minVal, double maxVal, + OffScreenLayerImageControl offScreenImageControl, + BufferedImage cacheImg, double cacheImgScaleX, double cacheImgScaleY, + MapTileRendererCalculator rendererCalculator, boolean useArrows) { + return pt -> { + try { + if (abortIndicator.get()) + return; + + double v = (double) pt.value; + + if (clampToFit + && (Double.compare(v, minVal) < 0 || Double.compare(v, maxVal) > 0)) + return; + + Color color = colormap.getColor(ColorMapUtils.getColorIndexZeroToOneLog10(v, minVal, maxVal)); + if (useArrows && false) { + try { + DataPointXYPolar ptPloar = (DataPointXYPolar) pt; + Graphics2D g2 = (Graphics2D) offScreenImageControl.getImageGraphics(); + g2.setColor(color); + g2.translate((ptPloar.point.getX() + offScreenImageControl.getOffScreenBufferPixel()), + (ptPloar.point.getY() + offScreenImageControl.getOffScreenBufferPixel())); + double rot = ptPloar.directionRads + Math.PI / 2. - rendererCalculator.getRotation(); + g2.rotate(rot); + g2.fill(arrow); + g2.rotate(-rot); + } catch (Exception e) { + //NeptusLog.pub().trace(e); + } + } else { + cacheImg.setRGB((int) ((pt.point.getX() + offScreenImageControl.getOffScreenBufferPixel()) * cacheImgScaleX), + (int) ((pt.point.getY() + offScreenImageControl.getOffScreenBufferPixel()) * cacheImgScaleY), color.getRGB()); + } + } + catch (Exception e) { + NeptusLog.pub().trace(e); + } + }; + } + + private List transformDataPointsToXY(List points, MapTileRendererCalculator rendererCalculator) { return points.stream().collect(ArrayList::new, (r, p) -> { if (abortIndicator.get()) { @@ -613,6 +830,49 @@ private ArrayList transformDataPointsToXY(List points, M }); } + private List transformCurrentDataPointsToXYPolar(List points, + double waterCurrentDepth, int waterCurrentDepthWindow, + MapTileRendererCalculator rendererCalculator) { + final double minDepth = waterCurrentDepth - waterCurrentDepthWindow; + final double maxDepth = waterCurrentDepth + waterCurrentDepthWindow; + return points.stream().filter(dp -> dp.zDown >= minDepth && dp.zDown <= maxDepth) + .collect(ArrayList::new, + (r, p) -> { + if (abortIndicator.get()) { + return; + } + Point2D pxy = rendererCalculator.getScreenPosition(p.location); + DataPointXYPolar dpxy = new DataPointXYPolar(); + dpxy.point = pxy; + dpxy.value = p.value; + dpxy.directionRads = p.directionRads; + dpxy.zDown = p.zDown; + r.add(dpxy); + }, (r1, r2) -> { + for (DataPointXYPolar d2 : r2) { + if (abortIndicator.get()) { + break; + } + boolean found = false; + for (DataPointXYPolar d1 : r1) { + if (abortIndicator.get()) { + break; + } + if (d2.point.equals(d1.point)) { + d1.value = (d1.value + d2.value) / 2.; + d1.directionRads = (d1.directionRads + d2.directionRads) / 2.; + d1.zDown = (d1.zDown + d2.zDown) / 2.; + found = true; + break; + } + } + if (!found) { + r1.add(d2); + } + } + }); + } + private static BufferedImage createBufferedImage(int cacheImgWidth, int cacheImgHeight, int translucent) { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gs = ge.getDefaultScreenDevice(); @@ -620,21 +880,72 @@ private static BufferedImage createBufferedImage(int cacheImgWidth, int cacheImg return gc.createCompatibleImage((int) cacheImgWidth , (int) cacheImgHeight , Transparency.TRANSLUCENT); } + private void paintColorbars(Graphics2D go, StateRenderer2D renderer) { + int offsetHeight = 130 * 2; + int offsetWidth = 5; + int offsetDelta = 130; + + if (showTemp) { + Graphics2D gl = (Graphics2D) go.create(); + gl.translate(offsetWidth, offsetHeight); + ColorBarPainterUtil.paintColorBar(go, colormapTemp, "Temperature", "ºC", minTemp, maxTemp); + gl.dispose(); + offsetHeight += offsetDelta; + } else if (showSal) { + Graphics2D gl = (Graphics2D) go.create(); + gl.translate(offsetWidth, offsetHeight); + ColorBarPainterUtil.paintColorBar(go, colormapSal, "Salinity", "PSU", minSal, maxSal); + gl.dispose(); + offsetHeight += offsetDelta; + } else if (showTurbidity) { + Graphics2D gl = (Graphics2D) go.create(); + gl.translate(offsetWidth, offsetHeight); + ColorBarPainterUtil.paintColorBar(go, colormapTurbidity, "Turbidity", "NTU", minTurbidity, maxTurbidity); + gl.dispose(); + offsetHeight += offsetDelta; + } else if (showChlorophyll) { + Graphics2D gl = (Graphics2D) go.create(); + gl.translate(offsetWidth, offsetHeight); + ColorBarPainterUtil.paintColorBar(go, colormapChlorophyll, "Chlorophyll", "µg/L", minChlorophyll, maxChlorophyll); + gl.dispose(); + offsetHeight += offsetDelta; + } else if (showDissolvedOrganicMatter) { + Graphics2D gl = (Graphics2D) go.create(); + gl.translate(offsetWidth, offsetHeight); + ColorBarPainterUtil.paintColorBar(go, colormapDissolvedOrganicMatter, "Dissolved Organic Matter", "PPB", minDissolvedOrganicMatter, maxDissolvedOrganicMatter); + gl.dispose(); + offsetHeight += offsetDelta; + } else if (showDissolvedOxygen) { + Graphics2D gl = (Graphics2D) go.create(); + gl.translate(offsetWidth, offsetHeight); + ColorBarPainterUtil.paintColorBar(go, colormapDissolvedOxygen, "Dissolved Oxygen", "µM", minDissolvedOxygen, maxDissolvedOxygen); + gl.dispose(); + offsetHeight += offsetDelta; + } else if (showAirSaturation) { + Graphics2D gl = (Graphics2D) go.create(); + gl.translate(offsetWidth, offsetHeight); + ColorBarPainterUtil.paintColorBar(go, colormapAirSaturation, "Air Saturation", "%", minAirSaturation, maxAirSaturation); + gl.dispose(); + offsetHeight += offsetDelta; + } else if (showWaterCurrent) { + Graphics2D gl = (Graphics2D) go.create(); + gl.translate(offsetWidth, offsetHeight); + String txtName = String.format("Water Current [%.2f ±%d]", waterCurrentDepth, waterCurrentDepthWindow); + ColorBarPainterUtil.paintColorBar(go, colormapWaterCurrent, txtName, "m/s", minWaterCurrent, maxWaterCurrent); + gl.dispose(); + offsetHeight += offsetDelta; + } + } + /** * @param go * @param renderer */ - private void paintColorbars(Graphics2D go, StateRenderer2D renderer) { -// int offsetHeight = 130; -// int offsetWidth = 5; -// int offsetDelta = 130; -// if (showSal) { -// Graphics2D gl = (Graphics2D) go.create(); -// gl.translate(offsetWidth, offsetHeight); -// ColorBarPainterUtil.paintColorBar(gl, colorMapVar, I18n.text(info.name), info.unit, minValue, maxValue); -// gl.dispose(); -// offsetHeight += offsetDelta; -// } + private void paintColorbars(Graphics2D go, StateRenderer2D renderer, ColorMap colormap, String name, + String unit, double minValue, double maxValue) { + Graphics2D gl = (Graphics2D) go.create(); + ColorBarPainterUtil.paintColorBar(gl, colormap, name, unit, minValue, maxValue); + gl.dispose(); } /* (non-Javadoc) @@ -642,6 +953,7 @@ private void paintColorbars(Graphics2D go, StateRenderer2D renderer) { */ @Override public void preferencesUpdated() { + triggerAllImagesRebuild(); getConsole().repaint(); } } \ No newline at end of file From 3db4bc2aba5d2de4bb5f8e5787199ac9d0cb9ede Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 14 Jun 2024 17:00:04 +0100 Subject: [PATCH 11/92] comm/manager/imc/ImcMsgManager: Avoiding depth=-height on locations created. --- src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java index 3a04da2c66..a637567816 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java @@ -1495,6 +1495,7 @@ else if (portTcp == 0) { loc.setLatitudeDegs(Math.toDegrees(latRad)); loc.setLongitudeDegs(Math.toDegrees(lonRad)); loc.setHeight(height); + loc.setDepth(-1); long locTime = (long) (info.getTimeSentSec() * 1000); resSys.setLocation(loc, locTime); } From 99de3402ddb702dd950320e03341df4c2e1e6a9e Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 14 Jun 2024 17:00:22 +0100 Subject: [PATCH 12/92] comm/manager/imc/SystemImcMsgCommInfo: Avoiding depth=-height on locations created. --- .../pt/lsts/neptus/comm/manager/imc/SystemImcMsgCommInfo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/SystemImcMsgCommInfo.java b/src/java/pt/lsts/neptus/comm/manager/imc/SystemImcMsgCommInfo.java index ff78d87a54..c1f6c239c8 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/SystemImcMsgCommInfo.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/SystemImcMsgCommInfo.java @@ -342,7 +342,7 @@ protected boolean processMsgLocally(MessageInfo info, IMCMessage msg) { double lat = msg.getDouble("lat"); double lon = msg.getDouble("lon"); double height = msg.getDouble("height"); - msg.getDouble("depth"); + double depth = msg.getDouble("depth"); msg.getDouble("altitude"); double x = msg.getDouble("x"); double y = msg.getDouble("y"); @@ -355,6 +355,7 @@ protected boolean processMsgLocally(MessageInfo info, IMCMessage msg) { loc.setLatitudeRads(lat); loc.setLongitudeRads(lon); loc.setHeight(height); + loc.setDepth(depth); loc.setOffsetNorth(x); loc.setOffsetEast(y); loc.setOffsetDown(z); From 143c54db4bd7529a781ce339097bf3e97348e805 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 19 Jun 2024 18:32:37 +0100 Subject: [PATCH 13/92] comm/iridium/IridiumMessage: Added new UpdateDeviceActivation for adding recipient to caravel iridium sending. --- .../pt/lsts/neptus/comm/admin/CommsAdmin.java | 34 +++++- .../neptus/comm/iridium/IridiumMessage.java | 1 + .../comm/iridium/UpdateDeviceActivation.java | 109 ++++++++++++++++++ 3 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java diff --git a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java index fde40b410b..f6ae7fed34 100644 --- a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java +++ b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java @@ -41,6 +41,7 @@ import pt.lsts.neptus.comm.IMCSendMessageUtils; import pt.lsts.neptus.comm.iridium.ImcIridiumMessage; import pt.lsts.neptus.comm.iridium.IridiumManager; +import pt.lsts.neptus.comm.iridium.UpdateDeviceActivation; import pt.lsts.neptus.comm.manager.imc.ImcMsgManager; import pt.lsts.neptus.comm.manager.imc.ImcSystem; import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; @@ -49,11 +50,14 @@ import pt.lsts.neptus.util.conf.GeneralPreferences; import java.awt.Component; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -68,6 +72,7 @@ public class CommsAdmin { public static final int COMM_TIMEOUT_MILLIS = 20000; public static final int MAX_ACOMMS_PAYLOAD_SIZE = 998; public static final double TIMEOUT_ACOMMS_SECS = 60; + private int minutesBetweenDeviceActivationSendSeconds = 5; public enum CommChannelType { WIFI("WiFi", "Wi-Fi channel", "images/channels/wifi.png", @@ -132,6 +137,8 @@ public void setReliable(boolean reliable) { private ImcMsgManager imcMsgManager = null; private List channels = new ArrayList<>(); + private Map lastIridiumMessageSent = new HashMap<>(); + public CommsAdmin(ImcMsgManager imcMsgManager) { this.imcMsgManager = imcMsgManager; @@ -296,8 +303,9 @@ public ImcMsgManager.SendResult get(long timeout, TimeUnit unit) throws Interrup } break; case IRIDIUM: - sendViaIridium(destinationName, message, waiter); - return result; + sendDeviceActivationViaIridiumIfNeeded(destinationName); + sendViaIridium(destinationName, message, waiter); + return result; case GSM: default: break; @@ -379,7 +387,7 @@ public void sendViaIridium(String destination, IMCMessage message, ResultWaiter irMsgs = IridiumManager.iridiumEncode(message); } catch (Exception e) { - NeptusLog.pub().warn( "Send by Iridium :: " + e.getMessage()); + NeptusLog.pub().warn("Send by Iridium :: " + e.getMessage()); waiter.deliveryError(message, e); return; } @@ -407,4 +415,24 @@ public void sendViaIridium(String destination, IMCMessage message, ResultWaiter waiter.deliveryError(message, e); } } + + private void sendDeviceActivationViaIridiumIfNeeded(String destinationName) { + LocalDateTime lastSent = lastIridiumMessageSent.get(destinationName); + if (lastSent == null || lastSent.plusMinutes(minutesBetweenDeviceActivationSendSeconds).isAfter(LocalDateTime.now())) { + lastIridiumMessageSent.put(destinationName, LocalDateTime.now()); + int src = ImcMsgManager.getManager().getLocalId().intValue(); + int dst = IMCDefinition.getInstance().getResolver().resolve(destinationName); + UpdateDeviceActivation act = new UpdateDeviceActivation(); + act.setDestination(dst); + act.setSource(src); + act.timestampMillis = System.currentTimeMillis(); + act.setOperation(UpdateDeviceActivation.OperationType.OP_ACTIVATE); + act.setTimestamp(act.timestampMillis); + try { + IridiumManager.getManager().send(act); + } catch (Exception e) { + NeptusLog.pub().warn("Send by Iridium :: " + e.getMessage()); + } + } + } } diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java index ee695ae361..937ec6fc18 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java @@ -69,6 +69,7 @@ public IridiumMessage(int msgType) { iridiumTypes.put(2007, TargetAssetPosition.class); iridiumTypes.put(2010, ImcIridiumMessage.class); iridiumTypes.put(2011, ExtendedDeviceUpdate.class); + iridiumTypes.put(2012, UpdateDeviceActivation.class); } public byte[] serialize() throws Exception { diff --git a/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java b/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java new file mode 100644 index 0000000000..a977da35b8 --- /dev/null +++ b/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) + * All rights reserved. + * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal + * + * This file is part of Neptus, Command and Control Framework. + * + * Commercial Licence Usage + * Licencees holding valid commercial Neptus licences may use this file + * in accordance with the commercial licence agreement provided with the + * Software or, alternatively, in accordance with the terms contained in a + * written agreement between you and Universidade do Porto. For licensing + * terms, conditions, and further information contact lsts@fe.up.pt. + * + * Modified European Union Public Licence - EUPL v.1.1 Usage + * Alternatively, this file may be used under the terms of the Modified EUPL, + * Version 1.1 only (the "Licence"), appearing in the file LICENSE.md + * included in the packaging of this file. You may not use this work + * except in compliance with the Licence. Unless required by applicable + * law or agreed to in writing, software distributed under the Licence is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific + * language governing permissions and limitations at + * https://github.com/LSTS/neptus/blob/develop/LICENSE.md + * and http://ec.europa.eu/idabc/eupl.html. + * + * For more information please see . + * + * Author: pdias + * Jun 19, 2024 + */ +package pt.lsts.neptus.comm.iridium; + +import pt.lsts.imc.IMCInputStream; +import pt.lsts.imc.IMCMessage; +import pt.lsts.imc.IMCOutputStream; + +import java.util.Collection; +import java.util.Vector; + +/** + * @author zp + * + */ +public class UpdateDeviceActivation extends IridiumMessage { + + public static enum OperationType { + OP_DEACTIVATE, + OP_ACTIVATE; + + } + + public UpdateDeviceActivation() { + super(2012); + } + + + protected double timestamp = System.currentTimeMillis(); + protected OperationType operation = OperationType.OP_ACTIVATE; + + public double getTimestamp() { + return timestamp; + } + + public void setTimestamp(double timestamp) { + this.timestamp = timestamp; + } + + public OperationType getOperation() { + return operation; + } + + public void setOperation(OperationType operation) { + this.operation = operation; + } + + @Override + public int serializeFields(IMCOutputStream out) throws Exception { + out.writeDouble(timestampMillis); + out.writeByte(operation.ordinal()); + return 5; + } + + @Override + public int deserializeFields(IMCInputStream in) throws Exception { + try { + timestamp = in.readDouble(); + operation = OperationType.values()[in.readUnsignedByte()]; + } + catch (Exception e) { + // empty + } + return 5; + } + + @Override + public Collection asImc() { + return new Vector<>(); + } + + @Override + public String toString() { + String s = super.toString(); + s += "\t[timestamp: "+timestamp+"]\n"; + s += "\t[operation: "+operation.name()+"]\n"; + return s; + } +} From 39667b2ba6d0d1d5a0822150591610dbda50948b Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 19 Jun 2024 19:13:22 +0100 Subject: [PATCH 14/92] plugins/planning/plandb/MissionTreePanel: Add option to ask for one specific plan info. --- .../plugins/planning/MissionTreePanel.java | 23 +++++++++++++++++++ .../planning/plandb/PlanDBControl.java | 6 ++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java index d7706c5d7e..02a7df66d7 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java @@ -425,6 +425,22 @@ public void actionPerformed(ActionEvent e) { }); } + private void addActionSendPlanInfoRequest(final ConsoleLayout console2, final PlanDBControl pdbControl, + final ArrayList selectedItems, JPopupMenu popupMenu) { + if (!usePlanDBSyncFeatures) + return; + + popupMenu.add(I18n.textf("Get %planName info from %system", getPlanNamesString(selectedItems, true), console2.getMainSystem())) + .addActionListener(e -> { + for (NameId nameId : selectedItems) { + PlanType sel = (PlanType) nameId; + String mainSystem = console2.getMainSystem(); + pdbControl.setRemoteSystemId(mainSystem); + pdbControl.requestPlanInfo(sel.getId()); + } + }); + } + private StringBuilder getPlanNamesString(final ArrayList selectedItems, boolean plans) { StringBuilder objectNames = new StringBuilder(); @@ -640,6 +656,13 @@ public void mousePressed(MouseEvent e) { addActionSendPlan(getConsole(), pdbControl, toSend, popupMenu); if (toGetPlan.size() > 0) addActionGetRemotePlan(getConsole(), pdbControl, toGetPlan, popupMenu); + if (!toRemoveRemotely.isEmpty() || !toGetPlan.isEmpty()) { + ArrayList toGetInfo = new ArrayList<>(); + toGetInfo.addAll(toRemoveRemotely); + toGetInfo.addAll(toGetPlan); + toGetInfo = toGetInfo.stream().distinct().collect(ArrayList::new, ArrayList::add, ArrayList::addAll); + addActionSendPlanInfoRequest(getConsole(), pdbControl, toGetInfo, popupMenu); + } break; case Transponder: addActionAddNewTrans(popupMenu); diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java b/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java index 9a49f46d1b..7432fa6bb5 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java @@ -42,6 +42,7 @@ import pt.lsts.neptus.comm.manager.imc.ImcId16; import pt.lsts.neptus.comm.manager.imc.ImcMsgManager; import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; +import pt.lsts.neptus.i18n.I18n; import pt.lsts.neptus.messages.listener.MessageInfo; import pt.lsts.neptus.messages.listener.MessageListener; import pt.lsts.neptus.types.mission.MissionType; @@ -123,7 +124,10 @@ public boolean requestActivePlan() { public boolean requestPlanInfo(String plan_id) { IMCMessage imc_PlanDB = IMCDefinition.getInstance().create("PlanDB", "type", "REQUEST", "op", "GET_INFO", "request_id", IMCSendMessageUtils.getNextRequestId(), "plan_id", plan_id); - return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + // return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + return IMCSendMessageUtils.sendMessage(imc_PlanDB, ImcMsgManager.TRANSPORT_TCP, null, null, + I18n.text("Error sending plan info request"), true, "", + true, true, true, remoteSystemId); } public boolean deletePlan(String plan_id) { From 1ae3d7e07d708111741725e43db20e9813bcfa73 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 20 Jun 2024 17:32:11 +0100 Subject: [PATCH 15/92] comms/iridium/RockBlockIridiumMessenger: Fix for not reading MimeMultipart email. --- .../pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java index c374f04896..c592a1088e 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java @@ -288,7 +288,7 @@ public Collection pollMessages(Date timeSince) throws Exception if (m.getReceivedDate().before(timeSince)) { break; } - else { + else if (m.getContent() instanceof MimeMultipart) { MimeMultipart mime = (MimeMultipart) m.getContent(); for (int j = 0; j < mime.getCount(); j++) { BodyPart p = mime.getBodyPart(j); From 157a294110c23b6d280aa59d8e69b5842ac15cdc Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 20 Jun 2024 17:34:06 +0100 Subject: [PATCH 16/92] comms/iridium/CommsAdmin: Fix sending device activation. --- .../pt/lsts/neptus/comm/admin/CommsAdmin.java | 8 +++++--- .../comm/iridium/UpdateDeviceActivation.java | 20 +++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java index f6ae7fed34..91dc222186 100644 --- a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java +++ b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java @@ -47,6 +47,7 @@ import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; import pt.lsts.neptus.comm.manager.imc.MessageDeliveryListener; import pt.lsts.neptus.types.vehicle.VehicleType; +import pt.lsts.neptus.util.ByteUtil; import pt.lsts.neptus.util.conf.GeneralPreferences; import java.awt.Component; @@ -72,7 +73,7 @@ public class CommsAdmin { public static final int COMM_TIMEOUT_MILLIS = 20000; public static final int MAX_ACOMMS_PAYLOAD_SIZE = 998; public static final double TIMEOUT_ACOMMS_SECS = 60; - private int minutesBetweenDeviceActivationSendSeconds = 5; + private int minutesBetweenDeviceActivationSendMinutes = 5; public enum CommChannelType { WIFI("WiFi", "Wi-Fi channel", "images/channels/wifi.png", @@ -418,7 +419,7 @@ public void sendViaIridium(String destination, IMCMessage message, ResultWaiter private void sendDeviceActivationViaIridiumIfNeeded(String destinationName) { LocalDateTime lastSent = lastIridiumMessageSent.get(destinationName); - if (lastSent == null || lastSent.plusMinutes(minutesBetweenDeviceActivationSendSeconds).isAfter(LocalDateTime.now())) { + if (lastSent == null || lastSent.plusMinutes(minutesBetweenDeviceActivationSendMinutes).isAfter(LocalDateTime.now())) { lastIridiumMessageSent.put(destinationName, LocalDateTime.now()); int src = ImcMsgManager.getManager().getLocalId().intValue(); int dst = IMCDefinition.getInstance().getResolver().resolve(destinationName); @@ -427,8 +428,9 @@ private void sendDeviceActivationViaIridiumIfNeeded(String destinationName) { act.setSource(src); act.timestampMillis = System.currentTimeMillis(); act.setOperation(UpdateDeviceActivation.OperationType.OP_ACTIVATE); - act.setTimestamp(act.timestampMillis); + act.setTimestampSeconds(act.timestampMillis / 1000.); try { + NeptusLog.pub().warn(">>>> Send activation request <<<< " + ByteUtil.encodeToHex(act.serialize())); IridiumManager.getManager().send(act); } catch (Exception e) { NeptusLog.pub().warn("Send by Iridium :: " + e.getMessage()); diff --git a/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java b/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java index a977da35b8..fc4c035390 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java +++ b/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java @@ -56,15 +56,15 @@ public UpdateDeviceActivation() { } - protected double timestamp = System.currentTimeMillis(); + protected double timestampSeconds = System.currentTimeMillis() / 1000.; protected OperationType operation = OperationType.OP_ACTIVATE; - public double getTimestamp() { - return timestamp; + public double getTimestampSeconds() { + return timestampSeconds; } - public void setTimestamp(double timestamp) { - this.timestamp = timestamp; + public void setTimestampSeconds(double timestampSeconds) { + this.timestampSeconds = timestampSeconds; } public OperationType getOperation() { @@ -77,21 +77,21 @@ public void setOperation(OperationType operation) { @Override public int serializeFields(IMCOutputStream out) throws Exception { - out.writeDouble(timestampMillis); + out.writeDouble(timestampSeconds); out.writeByte(operation.ordinal()); - return 5; + return 9; } @Override public int deserializeFields(IMCInputStream in) throws Exception { try { - timestamp = in.readDouble(); + timestampSeconds = in.readDouble(); operation = OperationType.values()[in.readUnsignedByte()]; } catch (Exception e) { // empty } - return 5; + return 9; } @Override @@ -102,7 +102,7 @@ public Collection asImc() { @Override public String toString() { String s = super.toString(); - s += "\t[timestamp: "+timestamp+"]\n"; + s += "\t[timestampSeconds: "+timestampSeconds+"]\n"; s += "\t[operation: "+operation.name()+"]\n"; return s; } From cfdec8633dc81ff47a2c6ed2258d0b43ab1ec0df Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 20 Jun 2024 17:35:41 +0100 Subject: [PATCH 17/92] console/plugins/MissionTreePanel: Fix visibility for asking for getting plan info from vehicle. --- .../lsts/neptus/console/plugins/planning/MissionTreePanel.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java index 02a7df66d7..49295f7e23 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java @@ -656,8 +656,9 @@ public void mousePressed(MouseEvent e) { addActionSendPlan(getConsole(), pdbControl, toSend, popupMenu); if (toGetPlan.size() > 0) addActionGetRemotePlan(getConsole(), pdbControl, toGetPlan, popupMenu); - if (!toRemoveRemotely.isEmpty() || !toGetPlan.isEmpty()) { + if (!toSend.isEmpty() || !toRemoveRemotely.isEmpty() || !toGetPlan.isEmpty()) { ArrayList toGetInfo = new ArrayList<>(); + toGetInfo.addAll(toSend); toGetInfo.addAll(toRemoveRemotely); toGetInfo.addAll(toGetPlan); toGetInfo = toGetInfo.stream().distinct().collect(ArrayList::new, ArrayList::add, ArrayList::addAll); From 2a32ee2b0cb9758c19a1dc3c3cbc335d7a5dafc4 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 20 Jun 2024 17:36:06 +0100 Subject: [PATCH 18/92] console/plugins/MissionTreePanel: Small tweaks. --- .../console/plugins/planning/MissionTreePanel.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java index 49295f7e23..eba1c5f1c5 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java @@ -648,13 +648,13 @@ public void mousePressed(MouseEvent e) { NeptusLog.pub().error("The plan " + extendedTreeNode + " has no state."); } } - if (toRemoveRemotely.size() > 0) + if (!toRemoveRemotely.isEmpty()) addActionRemovePlanRemotely(getConsole(), pdbControl, toRemoveRemotely, popupMenu); - if (toRemoveLocally.size() > 0) + if (!toRemoveLocally.isEmpty()) addActionRemovePlanLocally(getConsole(), toRemoveLocally, popupMenu); - if (toSend.size() > 0) + if (!toSend.isEmpty()) addActionSendPlan(getConsole(), pdbControl, toSend, popupMenu); - if (toGetPlan.size() > 0) + if (!toGetPlan.isEmpty()) addActionGetRemotePlan(getConsole(), pdbControl, toGetPlan, popupMenu); if (!toSend.isEmpty() || !toRemoveRemotely.isEmpty() || !toGetPlan.isEmpty()) { ArrayList toGetInfo = new ArrayList<>(); @@ -682,10 +682,10 @@ public void mousePressed(MouseEvent e) { if (state == State.NOT_SYNC) notSyncTrans.add((TransponderElement) extendedTreeNode.getUserObject()); } - if (localTrans.size() > 0) { + if (!localTrans.isEmpty()) { addActionRemoveTrans(localTrans, popupMenu); } - if (notSyncTrans.size() > 0) { + if (!notSyncTrans.isEmpty()) { addActionGetRemoteTrans(getConsole(), popupMenu, notSyncTrans); } From 6bece02b8d5e1c776cf0cf539d7a361490bd33b3 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 20 Jun 2024 17:38:13 +0100 Subject: [PATCH 19/92] console/plugins/planning/plandb/PlanDBControl: Fix for updating GUI for when receives plan info. --- .../plugins/planning/plandb/PlanDBControl.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java b/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java index 7432fa6bb5..1bac11c645 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java @@ -32,8 +32,6 @@ */ package pt.lsts.neptus.console.plugins.planning.plandb; -import java.util.Vector; - import pt.lsts.imc.IMCDefinition; import pt.lsts.imc.IMCMessage; import pt.lsts.neptus.NeptusLog; @@ -48,6 +46,10 @@ import pt.lsts.neptus.types.mission.MissionType; import pt.lsts.neptus.types.mission.plan.PlanType; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + /** * @author zp * @@ -183,6 +185,14 @@ else if (msg.getString("op").equals("GET_INFO")) { PlanDBInfo pinfo = new PlanDBInfo(); pinfo.parseIMCMessage(msg.getMessage("arg")); remoteState.storedPlans.put(msg.getAsString("plan_id"), pinfo); + + try { + for (IPlanDBListener l : listeners) + l.dbInfoUpdated(remoteState); + } + catch (Exception e) { + e.printStackTrace(); + } } else if (msg.getString("op").equals("DEL")) { remoteState.storedPlans.remove(msg.getAsString("plan_id")); From c803da817c18dc2f016186250ccbf434596c9167 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 8 Jul 2024 16:49:12 +0100 Subject: [PATCH 20/92] comm/manager/imc/EntitiesResolver: Save to properties file the EntityList values. --- .../comm/manager/imc/EntitiesResolver.java | 72 +++++++++++++++---- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java b/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java index 853429ed7d..45cdb6e384 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java @@ -32,6 +32,8 @@ */ package pt.lsts.neptus.comm.manager.imc; +import java.io.File; +import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; @@ -39,33 +41,79 @@ import com.google.common.collect.HashBiMap; import pt.lsts.imc.EntityList; +import pt.lsts.imc.IMCMessage; +import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.util.PropertiesLoader; +import pt.lsts.neptus.util.conf.ConfigFetch; /** * @author zp * */ public class EntitiesResolver { + public static final String ENTITIES_RESOLVER_PROPERTIES_FILE = ".cache/db/entities-resolver.properties"; + + private static PropertiesLoader properties = null; + static { + String propertiesFile = ConfigFetch.resolvePathBasedOnConfigFile(ENTITIES_RESOLVER_PROPERTIES_FILE); + if (!new File(propertiesFile).exists()) { + String testFile = ConfigFetch.resolvePathBasedOnConfigFile("../" + ENTITIES_RESOLVER_PROPERTIES_FILE); + if (new File(testFile).exists()) + propertiesFile = testFile; + } + new File(propertiesFile).getParentFile().mkdirs(); + properties = new PropertiesLoader(propertiesFile, PropertiesLoader.PROPERTIES); + + while (properties.keys().hasMoreElements()) { + String key = properties.keys().nextElement().toString(); + String value = properties.getProperty(key); + setEntities(key, value, false); + } + } protected static LinkedHashMap> entitiesMap = new LinkedHashMap>(); public static final int DEFAULT_ENTITY = 255; - - + + public static void saveProperties() { + try { + properties.store("EntitiesResolver properties"); + } + catch (IOException e) { + NeptusLog.pub().error("saveProperties", e); + } + } + /** * Based on a EntityList message set all the messages for further queries * @param id Name of the name (String id) * @param message EntityList message */ public static void setEntities(String id, EntityList message) { - LinkedHashMap tlist = null; - tlist = message.getList(); - - BiMap aliases = HashBiMap.create(); - for (String key : tlist.keySet()) - aliases.put(Integer.parseInt(tlist.get(key)), key); - - entitiesMap.put(id, aliases); - } - + LinkedHashMap tlist = null; + tlist = message.getList(); + String listAsStr = IMCMessage.encodeTupleList(tlist); + setEntities(id, listAsStr, true); + } + + public static void setEntities(String id, String listAsStr, boolean save) { + LinkedHashMap tlist = null; + tlist = IMCMessage.decodeTupleList(listAsStr); + + BiMap aliases = HashBiMap.create(); + for (String key : tlist.keySet()) { + aliases.put(Integer.parseInt(tlist.get(key)), key); + } + + if (save) { + String old = properties.getProperty(id); + if (old == null || !old.equals(listAsStr)) { + properties.setProperty(id, listAsStr); + saveProperties(); + } + } + + entitiesMap.put(id, aliases); + } public static final Map getEntities(Object systemId) { return entitiesMap.get(systemId.toString()); } From 910948d077f36351eafec8cc31cbcf0d46e5ae5d Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 11 Jul 2024 13:04:13 +0100 Subject: [PATCH 21/92] comm/manager/imc/EntitiesResolver: Temporary removed save to properties file the EntityList values. Null pointer issue on loading. --- .../comm/manager/imc/EntitiesResolver.java | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java b/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java index 45cdb6e384..90e2d71632 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java @@ -32,20 +32,19 @@ */ package pt.lsts.neptus.comm.manager.imc; -import java.io.File; -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; - import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; - import pt.lsts.imc.EntityList; import pt.lsts.imc.IMCMessage; import pt.lsts.neptus.NeptusLog; import pt.lsts.neptus.util.PropertiesLoader; import pt.lsts.neptus.util.conf.ConfigFetch; +import java.io.File; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + /** * @author zp * @@ -53,34 +52,34 @@ public class EntitiesResolver { public static final String ENTITIES_RESOLVER_PROPERTIES_FILE = ".cache/db/entities-resolver.properties"; - private static PropertiesLoader properties = null; - static { - String propertiesFile = ConfigFetch.resolvePathBasedOnConfigFile(ENTITIES_RESOLVER_PROPERTIES_FILE); - if (!new File(propertiesFile).exists()) { - String testFile = ConfigFetch.resolvePathBasedOnConfigFile("../" + ENTITIES_RESOLVER_PROPERTIES_FILE); - if (new File(testFile).exists()) - propertiesFile = testFile; - } - new File(propertiesFile).getParentFile().mkdirs(); - properties = new PropertiesLoader(propertiesFile, PropertiesLoader.PROPERTIES); + //private static PropertiesLoader properties = null; + //static { + // String propertiesFile = ConfigFetch.resolvePathBasedOnConfigFile(ENTITIES_RESOLVER_PROPERTIES_FILE); + // if (!new File(propertiesFile).exists()) { + // String testFile = ConfigFetch.resolvePathBasedOnConfigFile("../" + ENTITIES_RESOLVER_PROPERTIES_FILE); + // if (new File(testFile).exists()) + // propertiesFile = testFile; + // } + // new File(propertiesFile).getParentFile().mkdirs(); + // properties = new PropertiesLoader(propertiesFile, PropertiesLoader.PROPERTIES); - while (properties.keys().hasMoreElements()) { - String key = properties.keys().nextElement().toString(); - String value = properties.getProperty(key); - setEntities(key, value, false); - } - } + // while (properties.keys().hasMoreElements()) { + // String key = properties.keys().nextElement().toString(); + // String value = properties.getProperty(key); + // //setEntities(key, value, false); + // } + //} protected static LinkedHashMap> entitiesMap = new LinkedHashMap>(); public static final int DEFAULT_ENTITY = 255; public static void saveProperties() { - try { - properties.store("EntitiesResolver properties"); - } - catch (IOException e) { - NeptusLog.pub().error("saveProperties", e); - } + //try { + // properties.store("EntitiesResolver properties"); + //} + //catch (IOException e) { + // NeptusLog.pub().error("saveProperties", e); + //} } /** @@ -104,13 +103,13 @@ public static void setEntities(String id, String listAsStr, boolean save) { aliases.put(Integer.parseInt(tlist.get(key)), key); } - if (save) { - String old = properties.getProperty(id); - if (old == null || !old.equals(listAsStr)) { - properties.setProperty(id, listAsStr); - saveProperties(); - } - } + //if (save) { + // String old = properties.getProperty(id); + // if (old == null || !old.equals(listAsStr)) { + // properties.setProperty(id, listAsStr); + // saveProperties(); + // } + //} entitiesMap.put(id, aliases); } From 9ed5ea8d2ffd021da90f270d11e99836df15900b Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 11 Jul 2024 13:05:27 +0100 Subject: [PATCH 22/92] console/plugins/EntityStatePanel: Adding button to request entities list (temporary icon for now). --- .../console/plugins/EntityStatePanel.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/java/pt/lsts/neptus/console/plugins/EntityStatePanel.java b/src/java/pt/lsts/neptus/console/plugins/EntityStatePanel.java index 3f50d865ec..e0f318a5f9 100644 --- a/src/java/pt/lsts/neptus/console/plugins/EntityStatePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/EntityStatePanel.java @@ -54,15 +54,23 @@ import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; +import javax.swing.text.html.parser.Entity; import com.google.common.eventbus.Subscribe; +import pt.lsts.imc.EntityList; import pt.lsts.imc.IMCMessage; import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.comm.IMCSendMessageUtils; import pt.lsts.neptus.comm.manager.imc.EntitiesResolver; +import pt.lsts.neptus.comm.manager.imc.ImcMsgManager; +import pt.lsts.neptus.comm.manager.imc.ImcSystem; +import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; +import pt.lsts.neptus.comm.manager.imc.MessageDeliveryListener; import pt.lsts.neptus.console.ConsoleLayout; import pt.lsts.neptus.console.ConsolePanel; import pt.lsts.neptus.console.events.ConsoleEventMainSystemChange; +import pt.lsts.neptus.console.notifications.Notification; import pt.lsts.neptus.gui.StatusLed; import pt.lsts.neptus.gui.ToolbarButton; import pt.lsts.neptus.i18n.I18n; @@ -91,6 +99,7 @@ public class EntityStatePanel extends ConsolePanel implements NeptusMessageListe private final Color COLOR_RED = Color.RED; private final Icon ICON_CLEAR = ImageUtils.getScaledIcon("images/buttons/clear.png", 16, 16); + private final Icon ICON_RQST = ImageUtils.getScaledIcon("images/buttons/log.png", 16, 16); // Events Data private LinkedHashMap dataMap = new LinkedHashMap(); @@ -160,6 +169,13 @@ public void actionPerformed(ActionEvent e) { } }); clearButton.setToolTipText(I18n.text("Clear table")); + ToolbarButton rqstEntListButton = new ToolbarButton(new AbstractAction("request", ICON_RQST) { + @Override + public void actionPerformed(ActionEvent e) { + sendEntityListRequestMsg();; + } + }); + rqstEntListButton.setToolTipText(I18n.text("Request entity list")); status = new StatusLed(); status.made5LevelIndicator(); status.setLevel(StatusLed.LEVEL_OFF); @@ -167,6 +183,7 @@ public void actionPerformed(ActionEvent e) { wPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); wPanel.add(status); wPanel.add(clearButton); + wPanel.add(rqstEntListButton); this.add(wPanel, BorderLayout.NORTH); } @@ -383,6 +400,69 @@ public void messageArrived(IMCMessage message) { } } + void sendEntityListRequestMsg() { + try { + NeptusLog.pub().debug("Sending '" + getConsole().getMainSystem() + " | " + + " EntityList request..."); + EntityList msg = new EntityList(); + msg.setOp(EntityList.OP.QUERY); + boolean ret = IMCSendMessageUtils.sendMessage(msg, ImcMsgManager.TRANSPORT_TCP, + createDefaultMessageDeliveryListener(), this, I18n.text("Error requesting EntityList"), + true, "", true, true, true, + getConsole().getMainSystem()); + } + catch (Exception e) { + NeptusLog.pub().warn(e); + } + } + + private MessageDeliveryListener createDefaultMessageDeliveryListener() { + return (new MessageDeliveryListener() { + + private String getDest(IMCMessage message) { + ImcSystem sys = message != null ? ImcSystemsHolder.lookupSystem(message.getDst()) : null; + String dest = sys != null ? sys.getName() : I18n.text("unknown destination"); + return dest; + } + + @Override + public void deliveryUnreacheable(IMCMessage message) { + post(Notification.error( + I18n.text("Delivering Message"), + I18n.textf("Message %messageType to %destination delivery destination unreacheable", + message.getAbbrev(), getDest(message)))); + } + + @Override + public void deliveryTimeOut(IMCMessage message) { + post(Notification.error( + I18n.text("Delivering Message"), + I18n.textf("Message %messageType to %destination delivery timeout", + message.getAbbrev(), getDest(message)))); + } + + @Override + public void deliveryError(IMCMessage message, Object error) { + post(Notification.error( + I18n.text("Delivering Message"), + I18n.textf("Message %messageType to %destination delivery error. (%error)", + message.getAbbrev(), getDest(message), error))); + } + + @Override + public void deliveryUncertain(IMCMessage message, Object msg) { + } + + @Override + public void deliverySuccess(IMCMessage message) { + // post(Notification.success( + // I18n.text("Delivering Message"), + // I18n.textf("Message %messageType to %destination delivery success", + // message.getAbbrev(), getDest(message)))); + } + }); + } + /** * This is for representing an {@link EntityStateType} in a JTable. * From fda0ebf2c324f4ed10ddfc763adcfee9af9ee706 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 11 Jul 2024 13:06:43 +0100 Subject: [PATCH 23/92] comm/admin/CommsAdmin: Fix requesting activation time calculation. --- src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java index 91dc222186..676af2ce91 100644 --- a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java +++ b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java @@ -419,7 +419,7 @@ public void sendViaIridium(String destination, IMCMessage message, ResultWaiter private void sendDeviceActivationViaIridiumIfNeeded(String destinationName) { LocalDateTime lastSent = lastIridiumMessageSent.get(destinationName); - if (lastSent == null || lastSent.plusMinutes(minutesBetweenDeviceActivationSendMinutes).isAfter(LocalDateTime.now())) { + if (lastSent == null || lastSent.plusMinutes(minutesBetweenDeviceActivationSendMinutes).isBefore(LocalDateTime.now())) { lastIridiumMessageSent.put(destinationName, LocalDateTime.now()); int src = ImcMsgManager.getManager().getLocalId().intValue(); int dst = IMCDefinition.getInstance().getResolver().resolve(destinationName); From 0125fb03d492cec3e4f5a8a003af7721991f56ac Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 15 Jul 2024 11:35:34 +0100 Subject: [PATCH 24/92] comms/iridium/RockBlockIridiumMessenger: Time ordering received messages before pushing to internal bus. --- .../pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java index c592a1088e..54170cf203 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java @@ -322,6 +322,7 @@ else if (m.getContent() instanceof MimeMultipart) { return new Vector<>(); } + messages.sort((m1, m2) -> Long.compare(m1.timestampMillis, m2.timestampMillis)); return messages; } From 4bc2d7428653b93fd73e024dd3794ad44a731862 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 18 Jul 2024 18:26:48 +0100 Subject: [PATCH 25/92] comm/iridium/IridiumMessage: Added new ImcFullIridiumMessage to serialize an IMC message with the header also. --- .../comm/iridium/ImcFullIridiumMessage.java | 94 +++++++++++++++++++ .../comm/iridium/ImcIridiumMessage.java | 8 +- .../neptus/comm/iridium/IridiumMessage.java | 1 + 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java diff --git a/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java b/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java new file mode 100644 index 0000000000..7437961fb4 --- /dev/null +++ b/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) + * All rights reserved. + * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal + * + * This file is part of Neptus, Command and Control Framework. + * + * Commercial Licence Usage + * Licencees holding valid commercial Neptus licences may use this file + * in accordance with the commercial licence agreement provided with the + * Software or, alternatively, in accordance with the terms contained in a + * written agreement between you and Universidade do Porto. For licensing + * terms, conditions, and further information contact lsts@fe.up.pt. + * + * Modified European Union Public Licence - EUPL v.1.1 Usage + * Alternatively, this file may be used under the terms of the Modified EUPL, + * Version 1.1 only (the "Licence"), appearing in the file LICENSE.md + * included in the packaging of this file. You may not use this work + * except in compliance with the Licence. Unless required by applicable + * law or agreed to in writing, software distributed under the Licence is + * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the Licence for the specific + * language governing permissions and limitations at + * https://github.com/LSTS/neptus/blob/develop/LICENSE.md + * and http://ec.europa.eu/idabc/eupl.html. + * + * For more information please see . + * + * Author: pdias + * 18 Jul, 2024 + */ +package pt.lsts.neptus.comm.iridium; + +import pt.lsts.imc.IMCDefinition; +import pt.lsts.imc.IMCInputStream; +import pt.lsts.imc.IMCMessage; +import pt.lsts.imc.IMCOutputStream; + +import java.util.Collection; +import java.util.Vector; + +/** + * @author pdias + * + */ +public class ImcFullIridiumMessage extends ImcIridiumMessage { + + protected IMCMessage msg; + + // 5 bytes for RB addressing, 6 bytes for type and timestamp, 6 bytes for IMC header + public static int MaxPayloadSize = 270 - 17; + + public ImcFullIridiumMessage() { + super(2013); + } + + @Override + public int serializeFields(IMCOutputStream out) throws Exception { + if (msg != null) { + IMCDefinition.getInstance().serialize(msg, out); + timestampMillis = msg.getTimestampMillis(); + int size = IMCDefinition.getInstance().serializationSize(msg); + return size; + } + return 0; + } + + @Override + public int deserializeFields(IMCInputStream in) throws Exception { + try { + msg = IMCDefinition.getInstance().unserialize(in); + timestampMillis = msg.getTimestampMillis(); + setSource(msg.getSrc()); + setDestination(msg.getDst()); + } + catch (Exception e) { + e.printStackTrace(); + } + return IMCDefinition.getInstance().serializationSize(msg); + } + + @Override + public Collection asImc() { + Vector vec = new Vector<>(); + if (msg != null) + vec.add(msg); + + //msg.setSrc(getSource()); + //msg.setDst(getDestination()); + //msg.setTimestampMillis(timestampMillis); + return vec; + } +} diff --git a/src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java b/src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java index 849798559a..2d3cac956f 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/ImcIridiumMessage.java @@ -53,8 +53,12 @@ public class ImcIridiumMessage extends IridiumMessage { public ImcIridiumMessage() { super(2010); - } - + } + + protected ImcIridiumMessage(int msgType) { + super(msgType); + } + @Override public int serializeFields(IMCOutputStream out) throws Exception { if (msg != null) { diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java index 937ec6fc18..32e699b116 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java @@ -70,6 +70,7 @@ public IridiumMessage(int msgType) { iridiumTypes.put(2010, ImcIridiumMessage.class); iridiumTypes.put(2011, ExtendedDeviceUpdate.class); iridiumTypes.put(2012, UpdateDeviceActivation.class); + iridiumTypes.put(2013, ImcFullIridiumMessage.class); } public byte[] serialize() throws Exception { From a2e2b16b848325fda8195866d6a10d62baa140d4 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 23 Jul 2024 11:42:18 +0100 Subject: [PATCH 26/92] conf/params/caravel: Updated parameters. # Conflicts: # conf/params/caravel.en_US.xml # conf/params/caravel.pt_PT.xml --- conf/params/caravel.en_US.xml | 1575 ++++++--------------------------- conf/params/caravel.pt_PT.xml | 1575 ++++++--------------------------- 2 files changed, 560 insertions(+), 2590 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 8f620c5116..66fb1c4279 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -451,6 +451,15 @@ + + Minimum Turning Error + real + developer + global + 25 + ° + Minimum heading error to consider vessel is turning (in degrees). +
@@ -864,7 +873,7 @@ string developer global - AirMar220WX + Entity label of 'AbsoluteWind' message @@ -873,7 +882,7 @@ string developer global - HemisphereGPS + GPS Entity label of 'Displacement' message @@ -1330,6 +1339,28 @@ Roll rate above which measurement is discarded. + + Corridor -- Width + real + developer + global + 5.0 + m + Width of corridor for attack entry angle + 1.0 + 50.0 + + + Corridor -- Entry Angle + real + developer + global + 15 + ° + Attack angle when lateral track error equals corridor width + 2 + 45 +
@@ -2068,82 +2099,6 @@ None, Debug, Trace, Spew
-
- - Entity Label - string - developer - global - CPU Scaling - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 0 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Set CPU In Mode - string - developer - global - powersave - - Set CPU In Mode. - - - Use Linux Liquorix - boolean - developer - global - false - - Use Linux Liquorix. - - - Set Maximum CPU Frequency in MHz - integer - developer - global - 500 - - Set Maximum CPU Frequency in MHz. - -
Entity Label @@ -2865,6 +2820,15 @@ Input timeout before error is thrown. 0.0 + + Reference Change Distance + real + developer + global + 20000.0 + m + Distance needed for reference change. +
@@ -3255,7 +3219,7 @@ string developer global - uart:///dev/ttyS2:115200 + uart:///dev/ttyCPC:115200 IO device URI in the form "uart://DEVICE:BAUD" @@ -3268,6 +3232,15 @@ Offset for the Voltage readings. + + Use LIDB for Iridium + boolean + developer + global + false + + Use LIDB for Iridium communication. + Operation Mode string @@ -3399,37 +3372,19 @@ string developer global - CPU1 + Private (CPU-MAIN) Power Channel Entity Label - - Power Channel 1 Turn On - boolean - developer - global - true - - Power Channel State - Power Channel 2 Entity Label string developer global - CPU2 + Private (CPU-AUX) Power Channel Entity Label - - Power Channel 2 Turn On - boolean - developer - global - false - - Power Channel State - Power Channel 3 Entity Label string @@ -3444,7 +3399,7 @@ boolean developer global - false + true Power Channel State @@ -3471,7 +3426,7 @@ string developer global - ETH + Private (ETH) Power Channel Entity Label @@ -3480,7 +3435,7 @@ boolean developer global - true + false Power Channel State @@ -3498,7 +3453,7 @@ boolean developer global - true + false Power Channel State @@ -3561,7 +3516,7 @@ string developer global - ECHOTRIP + Private (ECHOTRIP) Power Channel Entity Label @@ -3579,7 +3534,7 @@ string developer global - OXYGEN + Private (OXYGEN) Power Channel Entity Label @@ -3597,7 +3552,7 @@ string developer global - AIRMAR + Private (AIRMAR) Power Channel Entity Label @@ -3606,7 +3561,7 @@ boolean developer global - true + false Power Channel State @@ -3615,7 +3570,7 @@ string developer global - CTD + Private (CTD_P) Power Channel Entity Label @@ -3633,7 +3588,7 @@ string developer global - FLED + LED Power Channel Entity Label @@ -3651,7 +3606,7 @@ string developer global - ADCP_P + Private (DCP_P) Power Channel Entity Label @@ -3669,7 +3624,7 @@ string developer global - SPOT + Private (SPOT) Power Channel Entity Label @@ -3678,10 +3633,46 @@ boolean developer global + false + + Power Channel State + + + Power Channel 17 Entity Label + string + developer + global + ECHOMAX_P + + Power Channel Entity Label + + + Power Channel 17 Turn On + boolean + developer + global true Power Channel State + + Power Channel 18 Entity Label + string + developer + global + Private (MOBILE) + + Power Channel Entity Label + + + Power Channel 18 Turn On + boolean + developer + global + false + + Power Channel State + Power Data 1 Entity Label string @@ -3804,7 +3795,7 @@ string developer global - IMU + AHRS_P Power Data Label @@ -3831,7 +3822,7 @@ string developer global - CPU2 + CPU-AUX Power Data Label @@ -3840,7 +3831,7 @@ string developer global - CPU1 + CPU-MAIN Power Data Label @@ -3853,14 +3844,32 @@ Timeout Connection to CPC + + Is Main CPU + boolean + developer + global + false + + Is Main CPU + + + Set CPC to use NAV and Iridium at Boot + boolean + developer + global + false + + Set CPC to use NAV and Iridium at Boot. +
-
+
Entity Label string developer global - AIS + GPS Main entity label @@ -3878,7 +3887,7 @@ integer developer global - 10.0 + 30.0 @@ -3934,9 +3943,39 @@ string developer global - uart:///dev/ttyS10:38400 + uart:///dev/ttyS10:19200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 10.0 + s + Input timeout + 0.0 + + + Sentence Order + list:string + developer + global + GPGGA, GPROT + + Sentence order + + + Acquisition Frequency + integer + developer + global + 1 - Serial port device used to communicate with the sensor + Acquisition Frequency + 0 + 5 Initialization String 0 - Command @@ -4028,1012 +4067,80 @@ - - Sentence Order - list:string + + Initialization String 5 - Command + string developer global - Sentence order - - - Input Timeout - real - developer - global - 4.0 - s - Input timeout - 0.0 + - - AIS Error - Max - integer + + Initialization String 5 - Reply + string developer global - 3 + - Max erros for Ais messages parser + - - AIS Error - Interval - real + + Initialization String 6 - Command + string developer global - 10.0 + - Invertal for checking AIS errors + - - Power Channel + + Initialization String 6 - Reply string developer global - Power Channel + - - Log messages - boolean + + Initialization String 7 - Command + string developer global - false + - Add messages received to logs + -
-
- - Entity Label + + Initialization String 7 - Reply string developer global - AirMar120WX + - Main entity label + - - Execution Priority - integer + + Initialization String 8 - Command + string developer global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 5.0 - - - - - Deactivation Time - integer - developer - global - 5.0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - global - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - developer - - Visibility of the 'Active' parameter - - - Active - boolean - developer - global - 1 - - True to activate task, false otherwise - - - IO Port - Device - string - developer - global - uart:///dev/ttyS8:4800 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 4.0 - s - Input timeout - 0.0 - - - Angle offset - real - developer - global - 5 - ° - Angle offset for relative wind - -
-
- - Entity Label - string - developer - global - Fluorometers - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 0 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - maneuver - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - user - - Visibility of the 'Active' parameter - - - Active - boolean - user - maneuver - 1 - - True to activate task, false otherwise - - - Serial Port - Device - string - developer - global - /dev/ttyS11 - - Serial port device used to communicate with the sensor - - - Serial Port - Baud Rate - integer - developer - global - 19200 - - Serial port Baud Rate - - - Input Timeout - real - developer - global - 5.0 - s - Amount of seconds to wait for data before reporting an error - 2.0 - - - Device Serial Number - string - developer - global - BBFL2W-8379 - - Device's serial number. Required to check communication with device. - - - CDOM -- Dark Counts - integer - developer - global - 62 - - Signal output of the meter in clean water with black tape over detector - - - CDOM -- Scale Factor - real - developer - global - 0.0916 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Chlorophyll -- Dark Counts - integer - developer - global - 49 - - Signal output of the meter in clean water with black tape over detector - - - Chlorophyll -- Scale Factor - real - developer - global - 0.0073 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Turbidity -- Dark Counts - integer - developer - global - 51 - - Signal output of the meter in clean water with black tape over detector - - - Turbidity -- Scale Factor - real - developer - global - 0.0024 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Sampling Duration - real - user - maneuver - 0.0 - - Sampling duration in seconds - - - Sampling Period - real - user - maneuver - 0.0 - - Sampling period in seconds - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - -
-
- - Entity Label - string - developer - global - GPS - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 30.0 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - global - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - developer - - Visibility of the 'Active' parameter - - - Active - boolean - developer - global - 1 - - True to activate task, false otherwise - - - IO Port - Device - string - developer - global - uart:///dev/ttyS9:19200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 10.0 - s - Input timeout - 0.0 - - - Sentence Order - list:string - developer - global - GPGGA, GPROT - - Sentence order - - - Acquisition Frequency - integer - developer - global - 1 - - Acquisition Frequency - 0 - 5 - - - Initialization String 0 - Command - string - developer - global - - - - - - Initialization String 0 - Reply - string - developer - global - - - - - - Initialization String 1 - Command - string - developer - global - - - - - - Initialization String 1 - Reply - string - developer - global - - - - - - Initialization String 2 - Command - string - developer - global - - - - - - Initialization String 2 - Reply - string - developer - global - - - - - - Initialization String 3 - Command - string - developer - global - - - - - - Initialization String 3 - Reply - string - developer - global - - - - - - Initialization String 4 - Command - string - developer - global - - - - - - Initialization String 4 - Reply - string - developer - global - - - - - - Initialization String 5 - Command - string - developer - global - - - - - - Initialization String 5 - Reply - string - developer - global - - - - - - Initialization String 6 - Command - string - developer - global - - - - - - Initialization String 6 - Reply - string - developer - global - - - - - - Initialization String 7 - Command - string - developer - global - - - - - - Initialization String 7 - Reply - string - developer - global - - - - - - Initialization String 8 - Command - string - developer - global - - - - - - Initialization String 8 - Reply - string - developer - global - - - - - - Initialization String 9 - Command - string - developer - global - - - - - - Initialization String 9 - Reply - string - developer - global - - - - -
-
- - Entity Label - string - developer - global - AHRS - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 20.0 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - global - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - developer - - Visibility of the 'Active' parameter - - - Active - boolean - developer - global - 1 - - True to activate task, false otherwise - - - IO Port - Device - string - developer - global - uart:///dev/ttyS4 - - IO device URI in the form "uart://DEVICE".This device has only one baud rate. - - - Power Channel - Name - string - developer - global - - - Name of the power channel - - - Hard-Iron Calibration - list:real - developer - global - 0.0, 0.0, 0.0 - G - Hard-Iron calibration parameters - 3 - - - Output Frequency - integer - developer - global - 20 - Hz - Output frequency - 1 - 127 - - - Raw Data - boolean - developer - global - false - - Set to true to enable raw data output - - - Rotation Matrix - list:real - developer - global - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 - - Rotation matrix which is dependent of the mounting position - 9 - - - Timeout - Error - real - developer - global - 3.0 - s - Number of seconds without data before reporting an error - 1.0 - - - Timeout - Failure - real - developer - global - 6.0 - s - Number of seconds without data before restarting task - 1.0 - - - Last Calibration Time - string - user - global - N/A - - Date of last successful calibration - -
-
- - Entity Label - string - developer - global - ADCP - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 5 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - global - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - developer - - Visibility of the 'Active' parameter - - - Active - boolean - developer - global - 1 - - True to activate task, false otherwise - - - IO Port - Device - string - developer - global - uart:///dev/ttyS6:115200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - - - Start Acquisition - boolean - user - maneuver - false - - Start Acquisition. - - - Sample Time Duration - integer - user - maneuver - 60 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer - user - maneuver - 80 - - Periodicity of Data Sampling in seconds. - - - Initialization String 0 - Command - string - developer - global - SETDEFAULT,ALL - - - - - Initialization String 1 - Command - string - developer - global - SETPLAN,MIAVG=1,AVG=1,DIAVG=0,VD=0,MV=10,SA=35,BURST=1,MIBURST=3600,DIBURST=0,SV=0,FN="RAWDATA.ad2cp",SO=0,FREQ=500,NSTT=0\r\n - - - - - Initialization String 2 - Command - string - developer - global - SETAVG,NC=16,CS=4,BD=1.0,CY="ENU",PL=0,AI=1,VP=0.000,VR=5.0,DF=3,NPING=3,NB=4,CH=0,MUX=0,BW="NARROW",ALTI=1,BT=0,ICE=0,ALTISTART=0.5,ALTIEND=70,RAWALTI=60\r\n - - - - - Initialization String 3 - Command - string - developer - global - SETTMAVG,EN=1,CD=1,PD=1,AVG=1,TV=1,TA=1,TC=1,CY="ENU",FO=0,SO=1,DF=3,DISTILT=0,TPG=1,MAPBINS=0\r\n - - - - - Initialization String 4 - Command - string - developer - global - SETTMALTI,EN=1,TS=1,TQ=1,FO=0,SO=1,DF=200,TPR=0\r\n - - - - - Initialization String 5 - Command - string - developer - global - SETTMBURST,EN=0,NS=1,SO=0,FO=0,DF=3,ENAVG=0,CY="ENU",MAPBINS=0\r\n - - - - - Initialization String 6 - Command - string - developer - global - SETINST,BR=115200,RS=232,LED="ON",ORIENT="ZDOWN",CMTOUT=300,DMTOUT=60,CFMTOUT=60\r\n + - - Initialization String 7 - Command + + Initialization String 8 - Reply string developer global - SAVE,ALL\r\n + - - Initialization String 8 - Command + + Initialization String 9 - Command string developer global @@ -5041,8 +4148,8 @@ - - Initialization String 9 - Command + + Initialization String 9 - Reply string developer global @@ -5051,13 +4158,13 @@
-
+
Entity Label string developer global - Dissolved Oxygen + AHRS Main entity label @@ -5066,7 +4173,7 @@ integer developer global - 20 + 10 Execution priority @@ -5075,7 +4182,7 @@ integer developer global - 60 + 20.0 @@ -5131,238 +4238,87 @@ string developer global - uart:///dev/ttyS7:9600 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Measurement String Identifier - string - developer - global - 4835 - - Measurement command string identifier - - - Entity Label - Temperature - string - developer - global - CTD Temperature - - Entity label of the CTD - - - Entity Label - Depth - string - developer - global - CTD Depth - - Entity label of the CTD - - - Entity Label - Salinity - string - developer - global - CTD Salinity + uart:///dev/ttyS9 - Entity label of the CTD + IO device URI in the form "uart://DEVICE".This device has only one baud rate. Power Channel - Name string developer global - Dissolved Oxygen - - - - - Start Acquisition - boolean - user - maneuver - false - - Start Acquisition. - - - Sample Time Duration - integer - user - maneuver - 60 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer - user - maneuver - 80 - - Periodicity of Data Sampling in seconds. - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - -
-
- - Entity Label - string - developer - global - CTD - - Main entity label - - - Execution Priority - integer - developer - global - 10 + - Execution priority + Name of the power channel - - Activation Time - integer + + Hard-Iron Calibration + list:real developer global - 10.0 - - + 0.0, 0.0, 0.0 + G + Hard-Iron calibration parameters + 3 - - Deactivation Time + + Output Frequency integer developer global - 0 - - + 20 + Hz + Output frequency + 1 + 127 - - Debug Level - string + + Raw Data + boolean developer global - None + false - - None, Debug, Trace, Spew - None, Debug, Trace, Spew + Set to true to enable raw data output - - Active - Scope - string + + Rotation Matrix + list:real developer global - global + 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 - Scoped of the 'Active' parameter + Rotation matrix which is dependent of the mounting position + 9 - - Active - Visibility - string + + Timeout - Error + real developer global - developer - - Visibility of the 'Active' parameter + 3.0 + s + Number of seconds without data before reporting an error + 1.0 - - Active - boolean + + Timeout - Failure + real developer global - 1 - - True to activate task, false otherwise + 6.0 + s + Number of seconds without data before restarting task + 1.0 - - IO Port - Device + + Last Calibration Time string - developer - global - uart:///dev/ttyS5:115200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Start Acquisition - boolean - user - maneuver - true - - Controls sensor activation/deactivation - - - Sample Period (ms) - integer - user - global - 125 - ms - Sample period in milliseconds - - - Sample Time Duration - integer - user - maneuver - 5 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer user - maneuver - 20 - - Periodicity of Data Sampling in seconds. - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - - - Power Channel - Name - string - developer - global - RBRlegato3 - - - - - Input Timeout - real - developer global - 26 + N/A - Input timeout + Date of last successful calibration
@@ -6290,7 +5246,7 @@ list:string developer global - CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage + CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage, AirSaturation, Chlorophyll, Conductivity, Pressure, Salinity, Turbidity, WindSpeed List of messages to transport @@ -6487,7 +5443,7 @@ string developer global - /dev/ttyS3 + /dev/ttyS8 Serial port device used to communicate with the modem @@ -6545,6 +5501,35 @@ Serial port baud rate for 9523N Module + + Address Section + string + developer + global + Iridium Addresses + + Name of the configuration section with modem addresses + + + Transmission Window + real + user + global + 100 + + Window to prioritize Transmission over Reception + 5 + + + Reception Window + real + user + global + 100 + + Window to prioritize Reception over Transmission + 5 +
@@ -6684,7 +5669,7 @@ list:string developer global - Abort, Acceleration, AngularVelocity, Announce, Brake, ClockControl, CompassCalibration, Collision, ControlLoops, ControlParcel, CpuUsage, Current, DataSanity, DesiredControl, DesiredZ, DesiredHeading, DesiredHeadingRate, DesiredPath, DesiredPitch, DesiredSpeed, DesiredVelocity, DevCalibrationControl, DevCalibrationState, DevDataBinary, DevDataText, Distance, EmergencyControl, EmergencyControlState, EntityActivationState, EntityInfo, EntityList, EntityMonitoringState, EntityParameters, EntityState, EstimatedState, EstimatedStreamVelocity, EulerAngles, EulerAnglesDelta, FollowPath, FollowRefState, FuelLevel, Goto, GpsFix, GpsFixRejection, GroundVelocity, Heartbeat, IdleManeuver, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, Loiter, ManeuverControlState, ManeuverDone, NavigationData, NavigationUncertainty, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PlanStatistics, PopEntityParameters, PowerChannelControl, PowerChannelState, Pulse, PulseDetectionControl, PushEntityParameters, Rows, QueryEntityParameters, Reference, RemoteActions, RemoteActionsRequest, RemoteState, ReportControl, RSSI, SimAcousticMessage, SaveEntityParameters, SetEntityParameters, SimulatedState, Sms, SmsRequest, SmsStatus, StateReport, StationKeeping, StopManeuver, TCPRequest, TCPStatus, Teleoperation, TeleoperationDone, Temperature, TextMessage, TransmissionRequest, TransmissionStatus, UamRxFrame, UamTxFrame, UamTxStatus, UamRxRange, VehicleCommand, VehicleMedium, VehicleState, VelocityDelta, Voltage, YoYo, AbsoluteWind, AirSaturation, AisInfo, CurrentProfile, CurrentProfileCell, Displacement, DissolvedOxygen, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Abort, Acceleration, AngularVelocity, Announce, Brake, ClockControl, CompassCalibration, Collision, ControlLoops, ControlParcel, CpuUsage, Current, DataSanity, DesiredControl, DesiredZ, DesiredHeading, DesiredHeadingRate, DesiredPath, DesiredPitch, DesiredSpeed, DesiredVelocity, DevCalibrationControl, DevCalibrationState, DevDataBinary, DevDataText, Distance, EmergencyControl, EmergencyControlState, EntityActivationState, EntityInfo, EntityList, EntityMonitoringState, EntityParameters, EntityState, EstimatedState, EstimatedStreamVelocity, EulerAngles, EulerAnglesDelta, FollowPath, FollowRefState, FuelLevel, Goto, GpsFix, GpsFixRejection, GroundVelocity, Heartbeat, IdleManeuver, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, Loiter, ManeuverControlState, ManeuverDone, NavigationData, NavigationUncertainty, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PlanStatistics, PopEntityParameters, PowerChannelControl, PowerChannelState, Pulse, PulseDetectionControl, PushEntityParameters, Rows, QueryEntityParameters, Reference, RemoteActions, RemoteActionsRequest, RemoteState, ReportControl, RSSI, SimAcousticMessage, SaveEntityParameters, SetEntityParameters, SimulatedState, Sms, SmsRequest, SmsStatus, StateReport, StationKeeping, StopManeuver, TCPRequest, TCPStatus, Teleoperation, TeleoperationDone, Temperature, TextMessage, TransmissionRequest, TransmissionStatus, UamRxFrame, UamTxFrame, UamTxStatus, UamRxRange, VehicleCommand, VehicleMedium, VehicleState, VelocityDelta, Voltage, YoYo, AbsoluteWind, AirSaturation, AisInfo, Chlorophyll, Conductivity, CurrentProfile, CurrentProfileCell, Depth, Displacement, DissolvedOrganicMatter, DissolvedOxygen, ENCAwareness, Frequency, MagneticField, Pressure, Rpm, Salinity, ServoPosition, SetServoPosition, SetThrusterActuation, Turbidity, WindSpeed @@ -6841,7 +5826,7 @@ list:string developer global - Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation List of messages to transport diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index 5c165d6327..bfda4923ca 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -451,6 +451,15 @@ + + Minimum Turning Error + real + developer + global + 25 + ° + Minimum heading error to consider vessel is turning (in degrees). +
@@ -864,7 +873,7 @@ string developer global - AirMar220WX + Entity label of 'AbsoluteWind' message @@ -873,7 +882,7 @@ string developer global - HemisphereGPS + GPS Entity label of 'Displacement' message @@ -1330,6 +1339,28 @@ Roll rate above which measurement is discarded. + + Corridor -- Width + real + developer + global + 5.0 + m + Width of corridor for attack entry angle + 1.0 + 50.0 + + + Corridor -- Entry Angle + real + developer + global + 15 + ° + Attack angle when lateral track error equals corridor width + 2 + 45 +
@@ -2068,82 +2099,6 @@ None, Debug, Trace, Spew
-
- - Nome da Entidade - string - developer - global - CPU Scaling - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 0 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Set CPU In Mode - string - developer - global - powersave - - Set CPU In Mode. - - - Use Linux Liquorix - boolean - developer - global - false - - Use Linux Liquorix. - - - Set Maximum CPU Frequency in MHz - integer - developer - global - 500 - - Set Maximum CPU Frequency in MHz. - -
Nome da Entidade @@ -2865,6 +2820,15 @@ Input timeout before error is thrown. 0.0 + + Reference Change Distance + real + developer + global + 20000.0 + m + Distance needed for reference change. +
@@ -3255,7 +3219,7 @@ string developer global - uart:///dev/ttyS2:115200 + uart:///dev/ttyCPC:115200 IO device URI in the form "uart://DEVICE:BAUD" @@ -3268,6 +3232,15 @@ Offset for the Voltage readings. + + Use LIDB for Iridium + boolean + developer + global + false + + Use LIDB for Iridium communication. + Operation Mode string @@ -3399,37 +3372,19 @@ string developer global - CPU1 + Private (CPU-MAIN) Power Channel Entity Label - - Power Channel 1 Turn On - boolean - developer - global - true - - Power Channel State - Power Channel 2 Entity Label string developer global - CPU2 + Private (CPU-AUX) Power Channel Entity Label - - Power Channel 2 Turn On - boolean - developer - global - false - - Power Channel State - Power Channel 3 Entity Label string @@ -3444,7 +3399,7 @@ boolean developer global - false + true Power Channel State @@ -3471,7 +3426,7 @@ string developer global - ETH + Private (ETH) Power Channel Entity Label @@ -3480,7 +3435,7 @@ boolean developer global - true + false Power Channel State @@ -3498,7 +3453,7 @@ boolean developer global - true + false Power Channel State @@ -3561,7 +3516,7 @@ string developer global - ECHOTRIP + Private (ECHOTRIP) Power Channel Entity Label @@ -3579,7 +3534,7 @@ string developer global - OXYGEN + Private (OXYGEN) Power Channel Entity Label @@ -3597,7 +3552,7 @@ string developer global - AIRMAR + Private (AIRMAR) Power Channel Entity Label @@ -3606,7 +3561,7 @@ boolean developer global - true + false Power Channel State @@ -3615,7 +3570,7 @@ string developer global - CTD + Private (CTD_P) Power Channel Entity Label @@ -3633,7 +3588,7 @@ string developer global - FLED + LED Power Channel Entity Label @@ -3651,7 +3606,7 @@ string developer global - ADCP_P + Private (DCP_P) Power Channel Entity Label @@ -3669,7 +3624,7 @@ string developer global - SPOT + Private (SPOT) Power Channel Entity Label @@ -3678,10 +3633,46 @@ boolean developer global + false + + Power Channel State + + + Power Channel 17 Entity Label + string + developer + global + ECHOMAX_P + + Power Channel Entity Label + + + Power Channel 17 Turn On + boolean + developer + global true Power Channel State + + Power Channel 18 Entity Label + string + developer + global + Private (MOBILE) + + Power Channel Entity Label + + + Power Channel 18 Turn On + boolean + developer + global + false + + Power Channel State + Power Data 1 Entity Label string @@ -3804,7 +3795,7 @@ string developer global - IMU + AHRS_P Power Data Label @@ -3831,7 +3822,7 @@ string developer global - CPU2 + CPU-AUX Power Data Label @@ -3840,7 +3831,7 @@ string developer global - CPU1 + CPU-MAIN Power Data Label @@ -3853,14 +3844,32 @@ Timeout Connection to CPC + + Is Main CPU + boolean + developer + global + false + + Is Main CPU + + + Set CPC to use NAV and Iridium at Boot + boolean + developer + global + false + + Set CPC to use NAV and Iridium at Boot. +
-
+
Nome da Entidade string developer global - AIS + GPS Nome principal da entidade @@ -3878,7 +3887,7 @@ integer developer global - 10.0 + 30.0 @@ -3934,9 +3943,39 @@ string developer global - uart:///dev/ttyS10:38400 + uart:///dev/ttyS10:19200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 10.0 + s + Input timeout + 0.0 + + + Sentence Order + list:string + developer + global + GPGGA, GPROT + + Sentence order + + + Acquisition Frequency + integer + developer + global + 1 - Serial port device used to communicate with the sensor + Acquisition Frequency + 0 + 5 Initialization String 0 - Command @@ -4028,1012 +4067,80 @@ - - Sentence Order - list:string + + Initialization String 5 - Command + string developer global - Sentence order - - - Input Timeout - real - developer - global - 4.0 - s - Input timeout - 0.0 + - - AIS Error - Max - integer + + Initialization String 5 - Reply + string developer global - 3 + - Max erros for Ais messages parser + - - AIS Error - Interval - real + + Initialization String 6 - Command + string developer global - 10.0 + - Invertal for checking AIS errors + - - Power Channel + + Initialization String 6 - Reply string developer global - Power Channel + - - Log messages - boolean + + Initialization String 7 - Command + string developer global - false + - Add messages received to logs + -
-
- - Nome da Entidade + + Initialization String 7 - Reply string developer global - AirMar120WX + - Nome principal da entidade + - - Prioridade de Execução - integer + + Initialization String 8 - Command + string developer global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 5.0 - - - - - Tempo de Desativação - integer - developer - global - 5.0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - global - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - developer - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - developer - global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - IO Port - Device - string - developer - global - uart:///dev/ttyS8:4800 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 4.0 - s - Input timeout - 0.0 - - - Angle offset - real - developer - global - 5 - ° - Angle offset for relative wind - -
-
- - Nome da Entidade - string - developer - global - Fluorometers - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 0 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - maneuver - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - user - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - user - maneuver - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - Serial Port - Device - string - developer - global - /dev/ttyS11 - - Serial port device used to communicate with the sensor - - - Serial Port - Baud Rate - integer - developer - global - 19200 - - Serial port Baud Rate - - - Input Timeout - real - developer - global - 5.0 - s - Amount of seconds to wait for data before reporting an error - 2.0 - - - Device Serial Number - string - developer - global - BBFL2W-8379 - - Device's serial number. Required to check communication with device. - - - CDOM -- Dark Counts - integer - developer - global - 62 - - Signal output of the meter in clean water with black tape over detector - - - CDOM -- Scale Factor - real - developer - global - 0.0916 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Chlorophyll -- Dark Counts - integer - developer - global - 49 - - Signal output of the meter in clean water with black tape over detector - - - Chlorophyll -- Scale Factor - real - developer - global - 0.0073 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Turbidity -- Dark Counts - integer - developer - global - 51 - - Signal output of the meter in clean water with black tape over detector - - - Turbidity -- Scale Factor - real - developer - global - 0.0024 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Sampling Duration - real - user - maneuver - 0.0 - - Sampling duration in seconds - - - Sampling Period - real - user - maneuver - 0.0 - - Sampling period in seconds - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - -
-
- - Nome da Entidade - string - developer - global - GPS - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 30.0 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - global - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - developer - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - developer - global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - IO Port - Device - string - developer - global - uart:///dev/ttyS9:19200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 10.0 - s - Input timeout - 0.0 - - - Sentence Order - list:string - developer - global - GPGGA, GPROT - - Sentence order - - - Acquisition Frequency - integer - developer - global - 1 - - Acquisition Frequency - 0 - 5 - - - Initialization String 0 - Command - string - developer - global - - - - - - Initialization String 0 - Reply - string - developer - global - - - - - - Initialization String 1 - Command - string - developer - global - - - - - - Initialization String 1 - Reply - string - developer - global - - - - - - Initialization String 2 - Command - string - developer - global - - - - - - Initialization String 2 - Reply - string - developer - global - - - - - - Initialization String 3 - Command - string - developer - global - - - - - - Initialization String 3 - Reply - string - developer - global - - - - - - Initialization String 4 - Command - string - developer - global - - - - - - Initialization String 4 - Reply - string - developer - global - - - - - - Initialization String 5 - Command - string - developer - global - - - - - - Initialization String 5 - Reply - string - developer - global - - - - - - Initialization String 6 - Command - string - developer - global - - - - - - Initialization String 6 - Reply - string - developer - global - - - - - - Initialization String 7 - Command - string - developer - global - - - - - - Initialization String 7 - Reply - string - developer - global - - - - - - Initialization String 8 - Command - string - developer - global - - - - - - Initialization String 8 - Reply - string - developer - global - - - - - - Initialization String 9 - Command - string - developer - global - - - - - - Initialization String 9 - Reply - string - developer - global - - - - -
-
- - Nome da Entidade - string - developer - global - AHRS - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 20.0 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - global - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - developer - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - developer - global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - IO Port - Device - string - developer - global - uart:///dev/ttyS4 - - IO device URI in the form "uart://DEVICE".This device has only one baud rate. - - - Power Channel - Name - string - developer - global - - - Name of the power channel - - - Hard-Iron Calibration - list:real - developer - global - 0.0, 0.0, 0.0 - G - Hard-Iron calibration parameters - 3 - - - Output Frequency - integer - developer - global - 20 - Hz - Output frequency - 1 - 127 - - - Raw Data - boolean - developer - global - false - - Set to true to enable raw data output - - - Rotation Matrix - list:real - developer - global - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 - - Rotation matrix which is dependent of the mounting position - 9 - - - Timeout - Error - real - developer - global - 3.0 - s - Number of seconds without data before reporting an error - 1.0 - - - Timeout - Failure - real - developer - global - 6.0 - s - Number of seconds without data before restarting task - 1.0 - - - Last Calibration Time - string - user - global - N/A - - Date of last successful calibration - -
-
- - Nome da Entidade - string - developer - global - ADCP - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 5 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - global - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - developer - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - developer - global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - IO Port - Device - string - developer - global - uart:///dev/ttyS6:115200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - - - Start Acquisition - boolean - user - maneuver - false - - Start Acquisition. - - - Sample Time Duration - integer - user - maneuver - 60 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer - user - maneuver - 80 - - Periodicity of Data Sampling in seconds. - - - Initialization String 0 - Command - string - developer - global - SETDEFAULT,ALL - - - - - Initialization String 1 - Command - string - developer - global - SETPLAN,MIAVG=1,AVG=1,DIAVG=0,VD=0,MV=10,SA=35,BURST=1,MIBURST=3600,DIBURST=0,SV=0,FN="RAWDATA.ad2cp",SO=0,FREQ=500,NSTT=0\r\n - - - - - Initialization String 2 - Command - string - developer - global - SETAVG,NC=16,CS=4,BD=1.0,CY="ENU",PL=0,AI=1,VP=0.000,VR=5.0,DF=3,NPING=3,NB=4,CH=0,MUX=0,BW="NARROW",ALTI=1,BT=0,ICE=0,ALTISTART=0.5,ALTIEND=70,RAWALTI=60\r\n - - - - - Initialization String 3 - Command - string - developer - global - SETTMAVG,EN=1,CD=1,PD=1,AVG=1,TV=1,TA=1,TC=1,CY="ENU",FO=0,SO=1,DF=3,DISTILT=0,TPG=1,MAPBINS=0\r\n - - - - - Initialization String 4 - Command - string - developer - global - SETTMALTI,EN=1,TS=1,TQ=1,FO=0,SO=1,DF=200,TPR=0\r\n - - - - - Initialization String 5 - Command - string - developer - global - SETTMBURST,EN=0,NS=1,SO=0,FO=0,DF=3,ENAVG=0,CY="ENU",MAPBINS=0\r\n - - - - - Initialization String 6 - Command - string - developer - global - SETINST,BR=115200,RS=232,LED="ON",ORIENT="ZDOWN",CMTOUT=300,DMTOUT=60,CFMTOUT=60\r\n + - - Initialization String 7 - Command + + Initialization String 8 - Reply string developer global - SAVE,ALL\r\n + - - Initialization String 8 - Command + + Initialization String 9 - Command string developer global @@ -5041,8 +4148,8 @@ - - Initialization String 9 - Command + + Initialization String 9 - Reply string developer global @@ -5051,13 +4158,13 @@
-
+
Nome da Entidade string developer global - Dissolved Oxygen + AHRS Nome principal da entidade @@ -5066,7 +4173,7 @@ integer developer global - 20 + 10 Prioridade de execução @@ -5075,7 +4182,7 @@ integer developer global - 60 + 20.0 @@ -5131,238 +4238,87 @@ string developer global - uart:///dev/ttyS7:9600 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Measurement String Identifier - string - developer - global - 4835 - - Measurement command string identifier - - - Entity Label - Temperature - string - developer - global - CTD Temperature - - Entity label of the CTD - - - Entity Label - Depth - string - developer - global - CTD Depth - - Entity label of the CTD - - - Entity Label - Salinity - string - developer - global - CTD Salinity + uart:///dev/ttyS9 - Entity label of the CTD + IO device URI in the form "uart://DEVICE".This device has only one baud rate. Power Channel - Name string developer global - Dissolved Oxygen - - - - - Start Acquisition - boolean - user - maneuver - false - - Start Acquisition. - - - Sample Time Duration - integer - user - maneuver - 60 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer - user - maneuver - 80 - - Periodicity of Data Sampling in seconds. - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - -
-
- - Nome da Entidade - string - developer - global - CTD - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 + - Prioridade de execução + Name of the power channel - - Tempo de Ativação - integer + + Hard-Iron Calibration + list:real developer global - 10.0 - - + 0.0, 0.0, 0.0 + G + Hard-Iron calibration parameters + 3 - - Tempo de Desativação + + Output Frequency integer developer global - 0 - - + 20 + Hz + Output frequency + 1 + 127 - - Nível de Depuração - string + + Raw Data + boolean developer global - None + false - - None, Debug, Trace, Spew - None, Debug, Trace, Spew + Set to true to enable raw data output - - Ativa - Escopo - string + + Rotation Matrix + list:real developer global - global + 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 - Escopo do parâmetro 'Ativa' + Rotation matrix which is dependent of the mounting position + 9 - - Ativa - Visibilidade - string + + Timeout - Error + real developer global - developer - - Visibilidade do parâmetro 'Ativa' + 3.0 + s + Number of seconds without data before reporting an error + 1.0 - - Ativa - boolean + + Timeout - Failure + real developer global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário + 6.0 + s + Number of seconds without data before restarting task + 1.0 - - IO Port - Device + + Last Calibration Time string - developer - global - uart:///dev/ttyS5:115200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Start Acquisition - boolean - user - maneuver - true - - Controls sensor activation/deactivation - - - Sample Period (ms) - integer - user - global - 125 - ms - Sample period in milliseconds - - - Sample Time Duration - integer - user - maneuver - 5 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer user - maneuver - 20 - - Periodicity of Data Sampling in seconds. - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - - - Power Channel - Name - string - developer - global - RBRlegato3 - - - - - Input Timeout - real - developer global - 26 + N/A - Input timeout + Date of last successful calibration
@@ -6290,7 +5246,7 @@ list:string developer global - CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage + CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage, AirSaturation, Chlorophyll, Conductivity, Pressure, Salinity, Turbidity, WindSpeed List of messages to transport @@ -6487,7 +5443,7 @@ string developer global - /dev/ttyS3 + /dev/ttyS8 Serial port device used to communicate with the modem @@ -6545,6 +5501,35 @@ Serial port baud rate for 9523N Module + + Address Section + string + developer + global + Iridium Addresses + + Name of the configuration section with modem addresses + + + Transmission Window + real + user + global + 100 + + Window to prioritize Transmission over Reception + 5 + + + Reception Window + real + user + global + 100 + + Window to prioritize Reception over Transmission + 5 +
@@ -6684,7 +5669,7 @@ list:string developer global - Abort, Acceleration, AngularVelocity, Announce, Brake, ClockControl, CompassCalibration, Collision, ControlLoops, ControlParcel, CpuUsage, Current, DataSanity, DesiredControl, DesiredZ, DesiredHeading, DesiredHeadingRate, DesiredPath, DesiredPitch, DesiredSpeed, DesiredVelocity, DevCalibrationControl, DevCalibrationState, DevDataBinary, DevDataText, Distance, EmergencyControl, EmergencyControlState, EntityActivationState, EntityInfo, EntityList, EntityMonitoringState, EntityParameters, EntityState, EstimatedState, EstimatedStreamVelocity, EulerAngles, EulerAnglesDelta, FollowPath, FollowRefState, FuelLevel, Goto, GpsFix, GpsFixRejection, GroundVelocity, Heartbeat, IdleManeuver, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, Loiter, ManeuverControlState, ManeuverDone, NavigationData, NavigationUncertainty, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PlanStatistics, PopEntityParameters, PowerChannelControl, PowerChannelState, Pulse, PulseDetectionControl, PushEntityParameters, Rows, QueryEntityParameters, Reference, RemoteActions, RemoteActionsRequest, RemoteState, ReportControl, RSSI, SimAcousticMessage, SaveEntityParameters, SetEntityParameters, SimulatedState, Sms, SmsRequest, SmsStatus, StateReport, StationKeeping, StopManeuver, TCPRequest, TCPStatus, Teleoperation, TeleoperationDone, Temperature, TextMessage, TransmissionRequest, TransmissionStatus, UamRxFrame, UamTxFrame, UamTxStatus, UamRxRange, VehicleCommand, VehicleMedium, VehicleState, VelocityDelta, Voltage, YoYo, AbsoluteWind, AirSaturation, AisInfo, CurrentProfile, CurrentProfileCell, Displacement, DissolvedOxygen, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Abort, Acceleration, AngularVelocity, Announce, Brake, ClockControl, CompassCalibration, Collision, ControlLoops, ControlParcel, CpuUsage, Current, DataSanity, DesiredControl, DesiredZ, DesiredHeading, DesiredHeadingRate, DesiredPath, DesiredPitch, DesiredSpeed, DesiredVelocity, DevCalibrationControl, DevCalibrationState, DevDataBinary, DevDataText, Distance, EmergencyControl, EmergencyControlState, EntityActivationState, EntityInfo, EntityList, EntityMonitoringState, EntityParameters, EntityState, EstimatedState, EstimatedStreamVelocity, EulerAngles, EulerAnglesDelta, FollowPath, FollowRefState, FuelLevel, Goto, GpsFix, GpsFixRejection, GroundVelocity, Heartbeat, IdleManeuver, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, Loiter, ManeuverControlState, ManeuverDone, NavigationData, NavigationUncertainty, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PlanStatistics, PopEntityParameters, PowerChannelControl, PowerChannelState, Pulse, PulseDetectionControl, PushEntityParameters, Rows, QueryEntityParameters, Reference, RemoteActions, RemoteActionsRequest, RemoteState, ReportControl, RSSI, SimAcousticMessage, SaveEntityParameters, SetEntityParameters, SimulatedState, Sms, SmsRequest, SmsStatus, StateReport, StationKeeping, StopManeuver, TCPRequest, TCPStatus, Teleoperation, TeleoperationDone, Temperature, TextMessage, TransmissionRequest, TransmissionStatus, UamRxFrame, UamTxFrame, UamTxStatus, UamRxRange, VehicleCommand, VehicleMedium, VehicleState, VelocityDelta, Voltage, YoYo, AbsoluteWind, AirSaturation, AisInfo, Chlorophyll, Conductivity, CurrentProfile, CurrentProfileCell, Depth, Displacement, DissolvedOrganicMatter, DissolvedOxygen, ENCAwareness, Frequency, MagneticField, Pressure, Rpm, Salinity, ServoPosition, SetServoPosition, SetThrusterActuation, Turbidity, WindSpeed @@ -6841,7 +5826,7 @@ list:string developer global - Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation List of messages to transport From fa15ec2d06b591caf114053a1eabbeaafccc7f80 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 23 Jul 2024 11:31:54 +0100 Subject: [PATCH 27/92] conf/params/caravel: Updated parameters. # Conflicts: # conf/params/caravel.en_US.xml # conf/params/caravel.pt_PT.xml --- conf/params/caravel.en_US.xml | 1575 ++++++--------------------------- conf/params/caravel.pt_PT.xml | 1575 ++++++--------------------------- 2 files changed, 560 insertions(+), 2590 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 8f620c5116..66fb1c4279 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -451,6 +451,15 @@ + + Minimum Turning Error + real + developer + global + 25 + ° + Minimum heading error to consider vessel is turning (in degrees). +
@@ -864,7 +873,7 @@ string developer global - AirMar220WX + Entity label of 'AbsoluteWind' message @@ -873,7 +882,7 @@ string developer global - HemisphereGPS + GPS Entity label of 'Displacement' message @@ -1330,6 +1339,28 @@ Roll rate above which measurement is discarded. + + Corridor -- Width + real + developer + global + 5.0 + m + Width of corridor for attack entry angle + 1.0 + 50.0 + + + Corridor -- Entry Angle + real + developer + global + 15 + ° + Attack angle when lateral track error equals corridor width + 2 + 45 +
@@ -2068,82 +2099,6 @@ None, Debug, Trace, Spew
-
- - Entity Label - string - developer - global - CPU Scaling - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 0 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Set CPU In Mode - string - developer - global - powersave - - Set CPU In Mode. - - - Use Linux Liquorix - boolean - developer - global - false - - Use Linux Liquorix. - - - Set Maximum CPU Frequency in MHz - integer - developer - global - 500 - - Set Maximum CPU Frequency in MHz. - -
Entity Label @@ -2865,6 +2820,15 @@ Input timeout before error is thrown. 0.0 + + Reference Change Distance + real + developer + global + 20000.0 + m + Distance needed for reference change. +
@@ -3255,7 +3219,7 @@ string developer global - uart:///dev/ttyS2:115200 + uart:///dev/ttyCPC:115200 IO device URI in the form "uart://DEVICE:BAUD" @@ -3268,6 +3232,15 @@ Offset for the Voltage readings. + + Use LIDB for Iridium + boolean + developer + global + false + + Use LIDB for Iridium communication. + Operation Mode string @@ -3399,37 +3372,19 @@ string developer global - CPU1 + Private (CPU-MAIN) Power Channel Entity Label - - Power Channel 1 Turn On - boolean - developer - global - true - - Power Channel State - Power Channel 2 Entity Label string developer global - CPU2 + Private (CPU-AUX) Power Channel Entity Label - - Power Channel 2 Turn On - boolean - developer - global - false - - Power Channel State - Power Channel 3 Entity Label string @@ -3444,7 +3399,7 @@ boolean developer global - false + true Power Channel State @@ -3471,7 +3426,7 @@ string developer global - ETH + Private (ETH) Power Channel Entity Label @@ -3480,7 +3435,7 @@ boolean developer global - true + false Power Channel State @@ -3498,7 +3453,7 @@ boolean developer global - true + false Power Channel State @@ -3561,7 +3516,7 @@ string developer global - ECHOTRIP + Private (ECHOTRIP) Power Channel Entity Label @@ -3579,7 +3534,7 @@ string developer global - OXYGEN + Private (OXYGEN) Power Channel Entity Label @@ -3597,7 +3552,7 @@ string developer global - AIRMAR + Private (AIRMAR) Power Channel Entity Label @@ -3606,7 +3561,7 @@ boolean developer global - true + false Power Channel State @@ -3615,7 +3570,7 @@ string developer global - CTD + Private (CTD_P) Power Channel Entity Label @@ -3633,7 +3588,7 @@ string developer global - FLED + LED Power Channel Entity Label @@ -3651,7 +3606,7 @@ string developer global - ADCP_P + Private (DCP_P) Power Channel Entity Label @@ -3669,7 +3624,7 @@ string developer global - SPOT + Private (SPOT) Power Channel Entity Label @@ -3678,10 +3633,46 @@ boolean developer global + false + + Power Channel State + + + Power Channel 17 Entity Label + string + developer + global + ECHOMAX_P + + Power Channel Entity Label + + + Power Channel 17 Turn On + boolean + developer + global true Power Channel State + + Power Channel 18 Entity Label + string + developer + global + Private (MOBILE) + + Power Channel Entity Label + + + Power Channel 18 Turn On + boolean + developer + global + false + + Power Channel State + Power Data 1 Entity Label string @@ -3804,7 +3795,7 @@ string developer global - IMU + AHRS_P Power Data Label @@ -3831,7 +3822,7 @@ string developer global - CPU2 + CPU-AUX Power Data Label @@ -3840,7 +3831,7 @@ string developer global - CPU1 + CPU-MAIN Power Data Label @@ -3853,14 +3844,32 @@ Timeout Connection to CPC + + Is Main CPU + boolean + developer + global + false + + Is Main CPU + + + Set CPC to use NAV and Iridium at Boot + boolean + developer + global + false + + Set CPC to use NAV and Iridium at Boot. +
-
+
Entity Label string developer global - AIS + GPS Main entity label @@ -3878,7 +3887,7 @@ integer developer global - 10.0 + 30.0 @@ -3934,9 +3943,39 @@ string developer global - uart:///dev/ttyS10:38400 + uart:///dev/ttyS10:19200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 10.0 + s + Input timeout + 0.0 + + + Sentence Order + list:string + developer + global + GPGGA, GPROT + + Sentence order + + + Acquisition Frequency + integer + developer + global + 1 - Serial port device used to communicate with the sensor + Acquisition Frequency + 0 + 5 Initialization String 0 - Command @@ -4028,1012 +4067,80 @@ - - Sentence Order - list:string + + Initialization String 5 - Command + string developer global - Sentence order - - - Input Timeout - real - developer - global - 4.0 - s - Input timeout - 0.0 + - - AIS Error - Max - integer + + Initialization String 5 - Reply + string developer global - 3 + - Max erros for Ais messages parser + - - AIS Error - Interval - real + + Initialization String 6 - Command + string developer global - 10.0 + - Invertal for checking AIS errors + - - Power Channel + + Initialization String 6 - Reply string developer global - Power Channel + - - Log messages - boolean + + Initialization String 7 - Command + string developer global - false + - Add messages received to logs + -
-
- - Entity Label + + Initialization String 7 - Reply string developer global - AirMar120WX + - Main entity label + - - Execution Priority - integer + + Initialization String 8 - Command + string developer global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 5.0 - - - - - Deactivation Time - integer - developer - global - 5.0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - global - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - developer - - Visibility of the 'Active' parameter - - - Active - boolean - developer - global - 1 - - True to activate task, false otherwise - - - IO Port - Device - string - developer - global - uart:///dev/ttyS8:4800 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 4.0 - s - Input timeout - 0.0 - - - Angle offset - real - developer - global - 5 - ° - Angle offset for relative wind - -
-
- - Entity Label - string - developer - global - Fluorometers - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 0 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - maneuver - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - user - - Visibility of the 'Active' parameter - - - Active - boolean - user - maneuver - 1 - - True to activate task, false otherwise - - - Serial Port - Device - string - developer - global - /dev/ttyS11 - - Serial port device used to communicate with the sensor - - - Serial Port - Baud Rate - integer - developer - global - 19200 - - Serial port Baud Rate - - - Input Timeout - real - developer - global - 5.0 - s - Amount of seconds to wait for data before reporting an error - 2.0 - - - Device Serial Number - string - developer - global - BBFL2W-8379 - - Device's serial number. Required to check communication with device. - - - CDOM -- Dark Counts - integer - developer - global - 62 - - Signal output of the meter in clean water with black tape over detector - - - CDOM -- Scale Factor - real - developer - global - 0.0916 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Chlorophyll -- Dark Counts - integer - developer - global - 49 - - Signal output of the meter in clean water with black tape over detector - - - Chlorophyll -- Scale Factor - real - developer - global - 0.0073 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Turbidity -- Dark Counts - integer - developer - global - 51 - - Signal output of the meter in clean water with black tape over detector - - - Turbidity -- Scale Factor - real - developer - global - 0.0024 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Sampling Duration - real - user - maneuver - 0.0 - - Sampling duration in seconds - - - Sampling Period - real - user - maneuver - 0.0 - - Sampling period in seconds - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - -
-
- - Entity Label - string - developer - global - GPS - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 30.0 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - global - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - developer - - Visibility of the 'Active' parameter - - - Active - boolean - developer - global - 1 - - True to activate task, false otherwise - - - IO Port - Device - string - developer - global - uart:///dev/ttyS9:19200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 10.0 - s - Input timeout - 0.0 - - - Sentence Order - list:string - developer - global - GPGGA, GPROT - - Sentence order - - - Acquisition Frequency - integer - developer - global - 1 - - Acquisition Frequency - 0 - 5 - - - Initialization String 0 - Command - string - developer - global - - - - - - Initialization String 0 - Reply - string - developer - global - - - - - - Initialization String 1 - Command - string - developer - global - - - - - - Initialization String 1 - Reply - string - developer - global - - - - - - Initialization String 2 - Command - string - developer - global - - - - - - Initialization String 2 - Reply - string - developer - global - - - - - - Initialization String 3 - Command - string - developer - global - - - - - - Initialization String 3 - Reply - string - developer - global - - - - - - Initialization String 4 - Command - string - developer - global - - - - - - Initialization String 4 - Reply - string - developer - global - - - - - - Initialization String 5 - Command - string - developer - global - - - - - - Initialization String 5 - Reply - string - developer - global - - - - - - Initialization String 6 - Command - string - developer - global - - - - - - Initialization String 6 - Reply - string - developer - global - - - - - - Initialization String 7 - Command - string - developer - global - - - - - - Initialization String 7 - Reply - string - developer - global - - - - - - Initialization String 8 - Command - string - developer - global - - - - - - Initialization String 8 - Reply - string - developer - global - - - - - - Initialization String 9 - Command - string - developer - global - - - - - - Initialization String 9 - Reply - string - developer - global - - - - -
-
- - Entity Label - string - developer - global - AHRS - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 20.0 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - global - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - developer - - Visibility of the 'Active' parameter - - - Active - boolean - developer - global - 1 - - True to activate task, false otherwise - - - IO Port - Device - string - developer - global - uart:///dev/ttyS4 - - IO device URI in the form "uart://DEVICE".This device has only one baud rate. - - - Power Channel - Name - string - developer - global - - - Name of the power channel - - - Hard-Iron Calibration - list:real - developer - global - 0.0, 0.0, 0.0 - G - Hard-Iron calibration parameters - 3 - - - Output Frequency - integer - developer - global - 20 - Hz - Output frequency - 1 - 127 - - - Raw Data - boolean - developer - global - false - - Set to true to enable raw data output - - - Rotation Matrix - list:real - developer - global - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 - - Rotation matrix which is dependent of the mounting position - 9 - - - Timeout - Error - real - developer - global - 3.0 - s - Number of seconds without data before reporting an error - 1.0 - - - Timeout - Failure - real - developer - global - 6.0 - s - Number of seconds without data before restarting task - 1.0 - - - Last Calibration Time - string - user - global - N/A - - Date of last successful calibration - -
-
- - Entity Label - string - developer - global - ADCP - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 5 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Active - Scope - string - developer - global - global - - Scoped of the 'Active' parameter - - - Active - Visibility - string - developer - global - developer - - Visibility of the 'Active' parameter - - - Active - boolean - developer - global - 1 - - True to activate task, false otherwise - - - IO Port - Device - string - developer - global - uart:///dev/ttyS6:115200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - - - Start Acquisition - boolean - user - maneuver - false - - Start Acquisition. - - - Sample Time Duration - integer - user - maneuver - 60 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer - user - maneuver - 80 - - Periodicity of Data Sampling in seconds. - - - Initialization String 0 - Command - string - developer - global - SETDEFAULT,ALL - - - - - Initialization String 1 - Command - string - developer - global - SETPLAN,MIAVG=1,AVG=1,DIAVG=0,VD=0,MV=10,SA=35,BURST=1,MIBURST=3600,DIBURST=0,SV=0,FN="RAWDATA.ad2cp",SO=0,FREQ=500,NSTT=0\r\n - - - - - Initialization String 2 - Command - string - developer - global - SETAVG,NC=16,CS=4,BD=1.0,CY="ENU",PL=0,AI=1,VP=0.000,VR=5.0,DF=3,NPING=3,NB=4,CH=0,MUX=0,BW="NARROW",ALTI=1,BT=0,ICE=0,ALTISTART=0.5,ALTIEND=70,RAWALTI=60\r\n - - - - - Initialization String 3 - Command - string - developer - global - SETTMAVG,EN=1,CD=1,PD=1,AVG=1,TV=1,TA=1,TC=1,CY="ENU",FO=0,SO=1,DF=3,DISTILT=0,TPG=1,MAPBINS=0\r\n - - - - - Initialization String 4 - Command - string - developer - global - SETTMALTI,EN=1,TS=1,TQ=1,FO=0,SO=1,DF=200,TPR=0\r\n - - - - - Initialization String 5 - Command - string - developer - global - SETTMBURST,EN=0,NS=1,SO=0,FO=0,DF=3,ENAVG=0,CY="ENU",MAPBINS=0\r\n - - - - - Initialization String 6 - Command - string - developer - global - SETINST,BR=115200,RS=232,LED="ON",ORIENT="ZDOWN",CMTOUT=300,DMTOUT=60,CFMTOUT=60\r\n + - - Initialization String 7 - Command + + Initialization String 8 - Reply string developer global - SAVE,ALL\r\n + - - Initialization String 8 - Command + + Initialization String 9 - Command string developer global @@ -5041,8 +4148,8 @@ - - Initialization String 9 - Command + + Initialization String 9 - Reply string developer global @@ -5051,13 +4158,13 @@
-
+
Entity Label string developer global - Dissolved Oxygen + AHRS Main entity label @@ -5066,7 +4173,7 @@ integer developer global - 20 + 10 Execution priority @@ -5075,7 +4182,7 @@ integer developer global - 60 + 20.0 @@ -5131,238 +4238,87 @@ string developer global - uart:///dev/ttyS7:9600 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Measurement String Identifier - string - developer - global - 4835 - - Measurement command string identifier - - - Entity Label - Temperature - string - developer - global - CTD Temperature - - Entity label of the CTD - - - Entity Label - Depth - string - developer - global - CTD Depth - - Entity label of the CTD - - - Entity Label - Salinity - string - developer - global - CTD Salinity + uart:///dev/ttyS9 - Entity label of the CTD + IO device URI in the form "uart://DEVICE".This device has only one baud rate. Power Channel - Name string developer global - Dissolved Oxygen - - - - - Start Acquisition - boolean - user - maneuver - false - - Start Acquisition. - - - Sample Time Duration - integer - user - maneuver - 60 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer - user - maneuver - 80 - - Periodicity of Data Sampling in seconds. - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - -
-
- - Entity Label - string - developer - global - CTD - - Main entity label - - - Execution Priority - integer - developer - global - 10 + - Execution priority + Name of the power channel - - Activation Time - integer + + Hard-Iron Calibration + list:real developer global - 10.0 - - + 0.0, 0.0, 0.0 + G + Hard-Iron calibration parameters + 3 - - Deactivation Time + + Output Frequency integer developer global - 0 - - + 20 + Hz + Output frequency + 1 + 127 - - Debug Level - string + + Raw Data + boolean developer global - None + false - - None, Debug, Trace, Spew - None, Debug, Trace, Spew + Set to true to enable raw data output - - Active - Scope - string + + Rotation Matrix + list:real developer global - global + 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 - Scoped of the 'Active' parameter + Rotation matrix which is dependent of the mounting position + 9 - - Active - Visibility - string + + Timeout - Error + real developer global - developer - - Visibility of the 'Active' parameter + 3.0 + s + Number of seconds without data before reporting an error + 1.0 - - Active - boolean + + Timeout - Failure + real developer global - 1 - - True to activate task, false otherwise + 6.0 + s + Number of seconds without data before restarting task + 1.0 - - IO Port - Device + + Last Calibration Time string - developer - global - uart:///dev/ttyS5:115200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Start Acquisition - boolean - user - maneuver - true - - Controls sensor activation/deactivation - - - Sample Period (ms) - integer - user - global - 125 - ms - Sample period in milliseconds - - - Sample Time Duration - integer - user - maneuver - 5 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer user - maneuver - 20 - - Periodicity of Data Sampling in seconds. - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - - - Power Channel - Name - string - developer - global - RBRlegato3 - - - - - Input Timeout - real - developer global - 26 + N/A - Input timeout + Date of last successful calibration
@@ -6290,7 +5246,7 @@ list:string developer global - CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage + CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage, AirSaturation, Chlorophyll, Conductivity, Pressure, Salinity, Turbidity, WindSpeed List of messages to transport @@ -6487,7 +5443,7 @@ string developer global - /dev/ttyS3 + /dev/ttyS8 Serial port device used to communicate with the modem @@ -6545,6 +5501,35 @@ Serial port baud rate for 9523N Module + + Address Section + string + developer + global + Iridium Addresses + + Name of the configuration section with modem addresses + + + Transmission Window + real + user + global + 100 + + Window to prioritize Transmission over Reception + 5 + + + Reception Window + real + user + global + 100 + + Window to prioritize Reception over Transmission + 5 +
@@ -6684,7 +5669,7 @@ list:string developer global - Abort, Acceleration, AngularVelocity, Announce, Brake, ClockControl, CompassCalibration, Collision, ControlLoops, ControlParcel, CpuUsage, Current, DataSanity, DesiredControl, DesiredZ, DesiredHeading, DesiredHeadingRate, DesiredPath, DesiredPitch, DesiredSpeed, DesiredVelocity, DevCalibrationControl, DevCalibrationState, DevDataBinary, DevDataText, Distance, EmergencyControl, EmergencyControlState, EntityActivationState, EntityInfo, EntityList, EntityMonitoringState, EntityParameters, EntityState, EstimatedState, EstimatedStreamVelocity, EulerAngles, EulerAnglesDelta, FollowPath, FollowRefState, FuelLevel, Goto, GpsFix, GpsFixRejection, GroundVelocity, Heartbeat, IdleManeuver, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, Loiter, ManeuverControlState, ManeuverDone, NavigationData, NavigationUncertainty, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PlanStatistics, PopEntityParameters, PowerChannelControl, PowerChannelState, Pulse, PulseDetectionControl, PushEntityParameters, Rows, QueryEntityParameters, Reference, RemoteActions, RemoteActionsRequest, RemoteState, ReportControl, RSSI, SimAcousticMessage, SaveEntityParameters, SetEntityParameters, SimulatedState, Sms, SmsRequest, SmsStatus, StateReport, StationKeeping, StopManeuver, TCPRequest, TCPStatus, Teleoperation, TeleoperationDone, Temperature, TextMessage, TransmissionRequest, TransmissionStatus, UamRxFrame, UamTxFrame, UamTxStatus, UamRxRange, VehicleCommand, VehicleMedium, VehicleState, VelocityDelta, Voltage, YoYo, AbsoluteWind, AirSaturation, AisInfo, CurrentProfile, CurrentProfileCell, Displacement, DissolvedOxygen, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Abort, Acceleration, AngularVelocity, Announce, Brake, ClockControl, CompassCalibration, Collision, ControlLoops, ControlParcel, CpuUsage, Current, DataSanity, DesiredControl, DesiredZ, DesiredHeading, DesiredHeadingRate, DesiredPath, DesiredPitch, DesiredSpeed, DesiredVelocity, DevCalibrationControl, DevCalibrationState, DevDataBinary, DevDataText, Distance, EmergencyControl, EmergencyControlState, EntityActivationState, EntityInfo, EntityList, EntityMonitoringState, EntityParameters, EntityState, EstimatedState, EstimatedStreamVelocity, EulerAngles, EulerAnglesDelta, FollowPath, FollowRefState, FuelLevel, Goto, GpsFix, GpsFixRejection, GroundVelocity, Heartbeat, IdleManeuver, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, Loiter, ManeuverControlState, ManeuverDone, NavigationData, NavigationUncertainty, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PlanStatistics, PopEntityParameters, PowerChannelControl, PowerChannelState, Pulse, PulseDetectionControl, PushEntityParameters, Rows, QueryEntityParameters, Reference, RemoteActions, RemoteActionsRequest, RemoteState, ReportControl, RSSI, SimAcousticMessage, SaveEntityParameters, SetEntityParameters, SimulatedState, Sms, SmsRequest, SmsStatus, StateReport, StationKeeping, StopManeuver, TCPRequest, TCPStatus, Teleoperation, TeleoperationDone, Temperature, TextMessage, TransmissionRequest, TransmissionStatus, UamRxFrame, UamTxFrame, UamTxStatus, UamRxRange, VehicleCommand, VehicleMedium, VehicleState, VelocityDelta, Voltage, YoYo, AbsoluteWind, AirSaturation, AisInfo, Chlorophyll, Conductivity, CurrentProfile, CurrentProfileCell, Depth, Displacement, DissolvedOrganicMatter, DissolvedOxygen, ENCAwareness, Frequency, MagneticField, Pressure, Rpm, Salinity, ServoPosition, SetServoPosition, SetThrusterActuation, Turbidity, WindSpeed @@ -6841,7 +5826,7 @@ list:string developer global - Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation List of messages to transport diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index 5c165d6327..bfda4923ca 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -451,6 +451,15 @@ + + Minimum Turning Error + real + developer + global + 25 + ° + Minimum heading error to consider vessel is turning (in degrees). +
@@ -864,7 +873,7 @@ string developer global - AirMar220WX + Entity label of 'AbsoluteWind' message @@ -873,7 +882,7 @@ string developer global - HemisphereGPS + GPS Entity label of 'Displacement' message @@ -1330,6 +1339,28 @@ Roll rate above which measurement is discarded. + + Corridor -- Width + real + developer + global + 5.0 + m + Width of corridor for attack entry angle + 1.0 + 50.0 + + + Corridor -- Entry Angle + real + developer + global + 15 + ° + Attack angle when lateral track error equals corridor width + 2 + 45 +
@@ -2068,82 +2099,6 @@ None, Debug, Trace, Spew
-
- - Nome da Entidade - string - developer - global - CPU Scaling - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 0 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Set CPU In Mode - string - developer - global - powersave - - Set CPU In Mode. - - - Use Linux Liquorix - boolean - developer - global - false - - Use Linux Liquorix. - - - Set Maximum CPU Frequency in MHz - integer - developer - global - 500 - - Set Maximum CPU Frequency in MHz. - -
Nome da Entidade @@ -2865,6 +2820,15 @@ Input timeout before error is thrown. 0.0 + + Reference Change Distance + real + developer + global + 20000.0 + m + Distance needed for reference change. +
@@ -3255,7 +3219,7 @@ string developer global - uart:///dev/ttyS2:115200 + uart:///dev/ttyCPC:115200 IO device URI in the form "uart://DEVICE:BAUD" @@ -3268,6 +3232,15 @@ Offset for the Voltage readings. + + Use LIDB for Iridium + boolean + developer + global + false + + Use LIDB for Iridium communication. + Operation Mode string @@ -3399,37 +3372,19 @@ string developer global - CPU1 + Private (CPU-MAIN) Power Channel Entity Label - - Power Channel 1 Turn On - boolean - developer - global - true - - Power Channel State - Power Channel 2 Entity Label string developer global - CPU2 + Private (CPU-AUX) Power Channel Entity Label - - Power Channel 2 Turn On - boolean - developer - global - false - - Power Channel State - Power Channel 3 Entity Label string @@ -3444,7 +3399,7 @@ boolean developer global - false + true Power Channel State @@ -3471,7 +3426,7 @@ string developer global - ETH + Private (ETH) Power Channel Entity Label @@ -3480,7 +3435,7 @@ boolean developer global - true + false Power Channel State @@ -3498,7 +3453,7 @@ boolean developer global - true + false Power Channel State @@ -3561,7 +3516,7 @@ string developer global - ECHOTRIP + Private (ECHOTRIP) Power Channel Entity Label @@ -3579,7 +3534,7 @@ string developer global - OXYGEN + Private (OXYGEN) Power Channel Entity Label @@ -3597,7 +3552,7 @@ string developer global - AIRMAR + Private (AIRMAR) Power Channel Entity Label @@ -3606,7 +3561,7 @@ boolean developer global - true + false Power Channel State @@ -3615,7 +3570,7 @@ string developer global - CTD + Private (CTD_P) Power Channel Entity Label @@ -3633,7 +3588,7 @@ string developer global - FLED + LED Power Channel Entity Label @@ -3651,7 +3606,7 @@ string developer global - ADCP_P + Private (DCP_P) Power Channel Entity Label @@ -3669,7 +3624,7 @@ string developer global - SPOT + Private (SPOT) Power Channel Entity Label @@ -3678,10 +3633,46 @@ boolean developer global + false + + Power Channel State + + + Power Channel 17 Entity Label + string + developer + global + ECHOMAX_P + + Power Channel Entity Label + + + Power Channel 17 Turn On + boolean + developer + global true Power Channel State + + Power Channel 18 Entity Label + string + developer + global + Private (MOBILE) + + Power Channel Entity Label + + + Power Channel 18 Turn On + boolean + developer + global + false + + Power Channel State + Power Data 1 Entity Label string @@ -3804,7 +3795,7 @@ string developer global - IMU + AHRS_P Power Data Label @@ -3831,7 +3822,7 @@ string developer global - CPU2 + CPU-AUX Power Data Label @@ -3840,7 +3831,7 @@ string developer global - CPU1 + CPU-MAIN Power Data Label @@ -3853,14 +3844,32 @@ Timeout Connection to CPC + + Is Main CPU + boolean + developer + global + false + + Is Main CPU + + + Set CPC to use NAV and Iridium at Boot + boolean + developer + global + false + + Set CPC to use NAV and Iridium at Boot. +
-
+
Nome da Entidade string developer global - AIS + GPS Nome principal da entidade @@ -3878,7 +3887,7 @@ integer developer global - 10.0 + 30.0 @@ -3934,9 +3943,39 @@ string developer global - uart:///dev/ttyS10:38400 + uart:///dev/ttyS10:19200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 10.0 + s + Input timeout + 0.0 + + + Sentence Order + list:string + developer + global + GPGGA, GPROT + + Sentence order + + + Acquisition Frequency + integer + developer + global + 1 - Serial port device used to communicate with the sensor + Acquisition Frequency + 0 + 5 Initialization String 0 - Command @@ -4028,1012 +4067,80 @@ - - Sentence Order - list:string + + Initialization String 5 - Command + string developer global - Sentence order - - - Input Timeout - real - developer - global - 4.0 - s - Input timeout - 0.0 + - - AIS Error - Max - integer + + Initialization String 5 - Reply + string developer global - 3 + - Max erros for Ais messages parser + - - AIS Error - Interval - real + + Initialization String 6 - Command + string developer global - 10.0 + - Invertal for checking AIS errors + - - Power Channel + + Initialization String 6 - Reply string developer global - Power Channel + - - Log messages - boolean + + Initialization String 7 - Command + string developer global - false + - Add messages received to logs + -
-
- - Nome da Entidade + + Initialization String 7 - Reply string developer global - AirMar120WX + - Nome principal da entidade + - - Prioridade de Execução - integer + + Initialization String 8 - Command + string developer global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 5.0 - - - - - Tempo de Desativação - integer - developer - global - 5.0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - global - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - developer - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - developer - global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - IO Port - Device - string - developer - global - uart:///dev/ttyS8:4800 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 4.0 - s - Input timeout - 0.0 - - - Angle offset - real - developer - global - 5 - ° - Angle offset for relative wind - -
-
- - Nome da Entidade - string - developer - global - Fluorometers - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 0 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - maneuver - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - user - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - user - maneuver - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - Serial Port - Device - string - developer - global - /dev/ttyS11 - - Serial port device used to communicate with the sensor - - - Serial Port - Baud Rate - integer - developer - global - 19200 - - Serial port Baud Rate - - - Input Timeout - real - developer - global - 5.0 - s - Amount of seconds to wait for data before reporting an error - 2.0 - - - Device Serial Number - string - developer - global - BBFL2W-8379 - - Device's serial number. Required to check communication with device. - - - CDOM -- Dark Counts - integer - developer - global - 62 - - Signal output of the meter in clean water with black tape over detector - - - CDOM -- Scale Factor - real - developer - global - 0.0916 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Chlorophyll -- Dark Counts - integer - developer - global - 49 - - Signal output of the meter in clean water with black tape over detector - - - Chlorophyll -- Scale Factor - real - developer - global - 0.0073 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Turbidity -- Dark Counts - integer - developer - global - 51 - - Signal output of the meter in clean water with black tape over detector - - - Turbidity -- Scale Factor - real - developer - global - 0.0024 - - Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - - Sampling Duration - real - user - maneuver - 0.0 - - Sampling duration in seconds - - - Sampling Period - real - user - maneuver - 0.0 - - Sampling period in seconds - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - -
-
- - Nome da Entidade - string - developer - global - GPS - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 30.0 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - global - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - developer - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - developer - global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - IO Port - Device - string - developer - global - uart:///dev/ttyS9:19200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 10.0 - s - Input timeout - 0.0 - - - Sentence Order - list:string - developer - global - GPGGA, GPROT - - Sentence order - - - Acquisition Frequency - integer - developer - global - 1 - - Acquisition Frequency - 0 - 5 - - - Initialization String 0 - Command - string - developer - global - - - - - - Initialization String 0 - Reply - string - developer - global - - - - - - Initialization String 1 - Command - string - developer - global - - - - - - Initialization String 1 - Reply - string - developer - global - - - - - - Initialization String 2 - Command - string - developer - global - - - - - - Initialization String 2 - Reply - string - developer - global - - - - - - Initialization String 3 - Command - string - developer - global - - - - - - Initialization String 3 - Reply - string - developer - global - - - - - - Initialization String 4 - Command - string - developer - global - - - - - - Initialization String 4 - Reply - string - developer - global - - - - - - Initialization String 5 - Command - string - developer - global - - - - - - Initialization String 5 - Reply - string - developer - global - - - - - - Initialization String 6 - Command - string - developer - global - - - - - - Initialization String 6 - Reply - string - developer - global - - - - - - Initialization String 7 - Command - string - developer - global - - - - - - Initialization String 7 - Reply - string - developer - global - - - - - - Initialization String 8 - Command - string - developer - global - - - - - - Initialization String 8 - Reply - string - developer - global - - - - - - Initialization String 9 - Command - string - developer - global - - - - - - Initialization String 9 - Reply - string - developer - global - - - - -
-
- - Nome da Entidade - string - developer - global - AHRS - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 20.0 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - global - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - developer - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - developer - global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - IO Port - Device - string - developer - global - uart:///dev/ttyS4 - - IO device URI in the form "uart://DEVICE".This device has only one baud rate. - - - Power Channel - Name - string - developer - global - - - Name of the power channel - - - Hard-Iron Calibration - list:real - developer - global - 0.0, 0.0, 0.0 - G - Hard-Iron calibration parameters - 3 - - - Output Frequency - integer - developer - global - 20 - Hz - Output frequency - 1 - 127 - - - Raw Data - boolean - developer - global - false - - Set to true to enable raw data output - - - Rotation Matrix - list:real - developer - global - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 - - Rotation matrix which is dependent of the mounting position - 9 - - - Timeout - Error - real - developer - global - 3.0 - s - Number of seconds without data before reporting an error - 1.0 - - - Timeout - Failure - real - developer - global - 6.0 - s - Number of seconds without data before restarting task - 1.0 - - - Last Calibration Time - string - user - global - N/A - - Date of last successful calibration - -
-
- - Nome da Entidade - string - developer - global - ADCP - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 5 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Ativa - Escopo - string - developer - global - global - - Escopo do parâmetro 'Ativa' - - - Ativa - Visibilidade - string - developer - global - developer - - Visibilidade do parâmetro 'Ativa' - - - Ativa - boolean - developer - global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário - - - IO Port - Device - string - developer - global - uart:///dev/ttyS6:115200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - - - Start Acquisition - boolean - user - maneuver - false - - Start Acquisition. - - - Sample Time Duration - integer - user - maneuver - 60 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer - user - maneuver - 80 - - Periodicity of Data Sampling in seconds. - - - Initialization String 0 - Command - string - developer - global - SETDEFAULT,ALL - - - - - Initialization String 1 - Command - string - developer - global - SETPLAN,MIAVG=1,AVG=1,DIAVG=0,VD=0,MV=10,SA=35,BURST=1,MIBURST=3600,DIBURST=0,SV=0,FN="RAWDATA.ad2cp",SO=0,FREQ=500,NSTT=0\r\n - - - - - Initialization String 2 - Command - string - developer - global - SETAVG,NC=16,CS=4,BD=1.0,CY="ENU",PL=0,AI=1,VP=0.000,VR=5.0,DF=3,NPING=3,NB=4,CH=0,MUX=0,BW="NARROW",ALTI=1,BT=0,ICE=0,ALTISTART=0.5,ALTIEND=70,RAWALTI=60\r\n - - - - - Initialization String 3 - Command - string - developer - global - SETTMAVG,EN=1,CD=1,PD=1,AVG=1,TV=1,TA=1,TC=1,CY="ENU",FO=0,SO=1,DF=3,DISTILT=0,TPG=1,MAPBINS=0\r\n - - - - - Initialization String 4 - Command - string - developer - global - SETTMALTI,EN=1,TS=1,TQ=1,FO=0,SO=1,DF=200,TPR=0\r\n - - - - - Initialization String 5 - Command - string - developer - global - SETTMBURST,EN=0,NS=1,SO=0,FO=0,DF=3,ENAVG=0,CY="ENU",MAPBINS=0\r\n - - - - - Initialization String 6 - Command - string - developer - global - SETINST,BR=115200,RS=232,LED="ON",ORIENT="ZDOWN",CMTOUT=300,DMTOUT=60,CFMTOUT=60\r\n + - - Initialization String 7 - Command + + Initialization String 8 - Reply string developer global - SAVE,ALL\r\n + - - Initialization String 8 - Command + + Initialization String 9 - Command string developer global @@ -5041,8 +4148,8 @@ - - Initialization String 9 - Command + + Initialization String 9 - Reply string developer global @@ -5051,13 +4158,13 @@
-
+
Nome da Entidade string developer global - Dissolved Oxygen + AHRS Nome principal da entidade @@ -5066,7 +4173,7 @@ integer developer global - 20 + 10 Prioridade de execução @@ -5075,7 +4182,7 @@ integer developer global - 60 + 20.0 @@ -5131,238 +4238,87 @@ string developer global - uart:///dev/ttyS7:9600 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Measurement String Identifier - string - developer - global - 4835 - - Measurement command string identifier - - - Entity Label - Temperature - string - developer - global - CTD Temperature - - Entity label of the CTD - - - Entity Label - Depth - string - developer - global - CTD Depth - - Entity label of the CTD - - - Entity Label - Salinity - string - developer - global - CTD Salinity + uart:///dev/ttyS9 - Entity label of the CTD + IO device URI in the form "uart://DEVICE".This device has only one baud rate. Power Channel - Name string developer global - Dissolved Oxygen - - - - - Start Acquisition - boolean - user - maneuver - false - - Start Acquisition. - - - Sample Time Duration - integer - user - maneuver - 60 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer - user - maneuver - 80 - - Periodicity of Data Sampling in seconds. - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - -
-
- - Nome da Entidade - string - developer - global - CTD - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 + - Prioridade de execução + Name of the power channel - - Tempo de Ativação - integer + + Hard-Iron Calibration + list:real developer global - 10.0 - - + 0.0, 0.0, 0.0 + G + Hard-Iron calibration parameters + 3 - - Tempo de Desativação + + Output Frequency integer developer global - 0 - - + 20 + Hz + Output frequency + 1 + 127 - - Nível de Depuração - string + + Raw Data + boolean developer global - None + false - - None, Debug, Trace, Spew - None, Debug, Trace, Spew + Set to true to enable raw data output - - Ativa - Escopo - string + + Rotation Matrix + list:real developer global - global + 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 - Escopo do parâmetro 'Ativa' + Rotation matrix which is dependent of the mounting position + 9 - - Ativa - Visibilidade - string + + Timeout - Error + real developer global - developer - - Visibilidade do parâmetro 'Ativa' + 3.0 + s + Number of seconds without data before reporting an error + 1.0 - - Ativa - boolean + + Timeout - Failure + real developer global - 1 - - Verdadeiro para ativar tarefa, falso caso contrário + 6.0 + s + Number of seconds without data before restarting task + 1.0 - - IO Port - Device + + Last Calibration Time string - developer - global - uart:///dev/ttyS5:115200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Start Acquisition - boolean - user - maneuver - true - - Controls sensor activation/deactivation - - - Sample Period (ms) - integer - user - global - 125 - ms - Sample period in milliseconds - - - Sample Time Duration - integer - user - maneuver - 5 - - Sample Time Duration in seconds. - - - Periodicity of Data Sampling - integer user - maneuver - 20 - - Periodicity of Data Sampling in seconds. - - - Timeout Transmitting Iridium Message - integer - developer - global - 60 - - Timeout Transmitting Iridium Message. - - - Power Channel - Name - string - developer - global - RBRlegato3 - - - - - Input Timeout - real - developer global - 26 + N/A - Input timeout + Date of last successful calibration
@@ -6290,7 +5246,7 @@ list:string developer global - CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage + CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage, AirSaturation, Chlorophyll, Conductivity, Pressure, Salinity, Turbidity, WindSpeed List of messages to transport @@ -6487,7 +5443,7 @@ string developer global - /dev/ttyS3 + /dev/ttyS8 Serial port device used to communicate with the modem @@ -6545,6 +5501,35 @@ Serial port baud rate for 9523N Module + + Address Section + string + developer + global + Iridium Addresses + + Name of the configuration section with modem addresses + + + Transmission Window + real + user + global + 100 + + Window to prioritize Transmission over Reception + 5 + + + Reception Window + real + user + global + 100 + + Window to prioritize Reception over Transmission + 5 +
@@ -6684,7 +5669,7 @@ list:string developer global - Abort, Acceleration, AngularVelocity, Announce, Brake, ClockControl, CompassCalibration, Collision, ControlLoops, ControlParcel, CpuUsage, Current, DataSanity, DesiredControl, DesiredZ, DesiredHeading, DesiredHeadingRate, DesiredPath, DesiredPitch, DesiredSpeed, DesiredVelocity, DevCalibrationControl, DevCalibrationState, DevDataBinary, DevDataText, Distance, EmergencyControl, EmergencyControlState, EntityActivationState, EntityInfo, EntityList, EntityMonitoringState, EntityParameters, EntityState, EstimatedState, EstimatedStreamVelocity, EulerAngles, EulerAnglesDelta, FollowPath, FollowRefState, FuelLevel, Goto, GpsFix, GpsFixRejection, GroundVelocity, Heartbeat, IdleManeuver, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, Loiter, ManeuverControlState, ManeuverDone, NavigationData, NavigationUncertainty, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PlanStatistics, PopEntityParameters, PowerChannelControl, PowerChannelState, Pulse, PulseDetectionControl, PushEntityParameters, Rows, QueryEntityParameters, Reference, RemoteActions, RemoteActionsRequest, RemoteState, ReportControl, RSSI, SimAcousticMessage, SaveEntityParameters, SetEntityParameters, SimulatedState, Sms, SmsRequest, SmsStatus, StateReport, StationKeeping, StopManeuver, TCPRequest, TCPStatus, Teleoperation, TeleoperationDone, Temperature, TextMessage, TransmissionRequest, TransmissionStatus, UamRxFrame, UamTxFrame, UamTxStatus, UamRxRange, VehicleCommand, VehicleMedium, VehicleState, VelocityDelta, Voltage, YoYo, AbsoluteWind, AirSaturation, AisInfo, CurrentProfile, CurrentProfileCell, Displacement, DissolvedOxygen, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Abort, Acceleration, AngularVelocity, Announce, Brake, ClockControl, CompassCalibration, Collision, ControlLoops, ControlParcel, CpuUsage, Current, DataSanity, DesiredControl, DesiredZ, DesiredHeading, DesiredHeadingRate, DesiredPath, DesiredPitch, DesiredSpeed, DesiredVelocity, DevCalibrationControl, DevCalibrationState, DevDataBinary, DevDataText, Distance, EmergencyControl, EmergencyControlState, EntityActivationState, EntityInfo, EntityList, EntityMonitoringState, EntityParameters, EntityState, EstimatedState, EstimatedStreamVelocity, EulerAngles, EulerAnglesDelta, FollowPath, FollowRefState, FuelLevel, Goto, GpsFix, GpsFixRejection, GroundVelocity, Heartbeat, IdleManeuver, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, Loiter, ManeuverControlState, ManeuverDone, NavigationData, NavigationUncertainty, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PlanStatistics, PopEntityParameters, PowerChannelControl, PowerChannelState, Pulse, PulseDetectionControl, PushEntityParameters, Rows, QueryEntityParameters, Reference, RemoteActions, RemoteActionsRequest, RemoteState, ReportControl, RSSI, SimAcousticMessage, SaveEntityParameters, SetEntityParameters, SimulatedState, Sms, SmsRequest, SmsStatus, StateReport, StationKeeping, StopManeuver, TCPRequest, TCPStatus, Teleoperation, TeleoperationDone, Temperature, TextMessage, TransmissionRequest, TransmissionStatus, UamRxFrame, UamTxFrame, UamTxStatus, UamRxRange, VehicleCommand, VehicleMedium, VehicleState, VelocityDelta, Voltage, YoYo, AbsoluteWind, AirSaturation, AisInfo, Chlorophyll, Conductivity, CurrentProfile, CurrentProfileCell, Depth, Displacement, DissolvedOrganicMatter, DissolvedOxygen, ENCAwareness, Frequency, MagneticField, Pressure, Rpm, Salinity, ServoPosition, SetServoPosition, SetThrusterActuation, Turbidity, WindSpeed @@ -6841,7 +5826,7 @@ list:string developer global - Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation List of messages to transport From 65129397140443ab4eb68c961b27e89fb965373d Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 23 Jul 2024 18:11:20 +0100 Subject: [PATCH 28/92] console/plugins/planning/MissionTreePanel: Cleanup. --- .../plugins/planning/MissionTreePanel.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java index eba1c5f1c5..e5c8eb1f65 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java @@ -267,15 +267,16 @@ private void updatePlanDBListener(String id) { } private void removePlanDBListener() { - if (pdbControl != null) - pdbControl.removeListener(planDBListener); + if (pdbControl != null) { + pdbControl.removeListener(planDBListener); + } } @Override public Vector getSelectedPlans() { ArrayList selectedItems = browser.getSelectedItems(); Vector plans = new Vector(); - if (selectedItems.size() > 0) { + if (!selectedItems.isEmpty()) { for (NameId o : selectedItems) { if (o instanceof PlanType) plans.add((PlanType) o); @@ -334,7 +335,7 @@ public void on(PlanSpecification msg) { @Subscribe public void on(PlanControlState msg) { - // If vehicle stops, the timers stop as well + // If vehicle stops, the timers stop as well if (msg.getState() == STATE.READY || msg.getState() == STATE.BLOCKED) { browser.transStopTimers(); this.running = false; @@ -602,8 +603,10 @@ public void mousePressed(MouseEvent e) { switch (selecType) { case Plans: - if (selectedItems.size() == 1) + if (selectedItems.size() == 1) { addActionRenamePlan(getConsole(), selectedItems, popupMenu); + addForMainVehiclePlan = false; + } popupMenu.addSeparator(); // New @@ -693,7 +696,7 @@ public void mousePressed(MouseEvent e) { // Switch JMenu switchM = new JMenu(I18n.text("Switch")); ArrayList transponders = browser.getTransponders(); - if (transponders.size() > 0) { + if (!transponders.isEmpty()) { TransponderElement transA, transB; for (int iA = 0; iA < transponders.size(); iA++) { transA = transponders.get(iA); From 8bb0dd0c79245741afa269459243dd744b07b3be Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 23 Jul 2024 18:12:48 +0100 Subject: [PATCH 29/92] console/plugins/planning/MissionTreePanel: Cleanup visibility for asking for getting plan and info from vehicle. --- .../plugins/planning/MissionTreePanel.java | 69 ++++++++++++++++--- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java index e5c8eb1f65..4871bb68e4 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java @@ -62,6 +62,8 @@ import pt.lsts.imc.PlanControlState; import pt.lsts.imc.PlanControlState.STATE; import pt.lsts.imc.PlanSpecification; +import pt.lsts.imc.StateReport; +import pt.lsts.imc.state.ImcSystemState; import pt.lsts.neptus.NeptusLog; import pt.lsts.neptus.comm.IMCSendMessageUtils; import pt.lsts.neptus.comm.IMCUtils; @@ -134,6 +136,8 @@ public class MissionTreePanel extends ConsolePanel protected MissionBrowser browser = new MissionBrowser(); protected PlanDBControl pdbControl; + protected String mainVehicleLastPlanId = null; + /** * This adapter is called by a class monitoring PlanDB messages. It is only called if a PlanDB message with field * type set to success is received. @@ -208,6 +212,23 @@ public void actionPerformed(ActionEvent e) { }); } + @Subscribe + public void mainVehicleChangeNotification(ConsoleEventMainSystemChange ev) { + mainVehicleLastPlanId = null; + try { + ImcSystemState state = getConsole().getImcMsgManager().getState(getMainVehicleId()); + if (state != null) { + PlanControlState pcsMsg = state.last(PlanControlState.class); + if (pcsMsg != null) { + on(pcsMsg); + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + @Subscribe public void on(ConsoleEventMainSystemChange evt) { running = false; @@ -335,6 +356,10 @@ public void on(PlanSpecification msg) { @Subscribe public void on(PlanControlState msg) { + if (getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { + mainVehicleLastPlanId = msg.getPlanId(); + } + // If vehicle stops, the timers stop as well if (msg.getState() == STATE.READY || msg.getState() == STATE.BLOCKED) { browser.transStopTimers(); @@ -600,6 +625,14 @@ public void mousePressed(MouseEvent e) { ArrayList toShare = new ArrayList(); + ArrayList toRemoveLocally = new ArrayList(); + ArrayList toRemoveRemotely = new ArrayList(); + ArrayList toGetPlan = new ArrayList(); + ArrayList toGetPlanInfo = new ArrayList(); + ArrayList toSend = new ArrayList(); + + boolean addForMainVehiclePlan = mainVehicleLastPlanId != null; + switch (selecType) { case Plans: @@ -609,19 +642,19 @@ public void mousePressed(MouseEvent e) { } popupMenu.addSeparator(); - // New - ArrayList toRemoveLocally = new ArrayList(); - ArrayList toRemoveRemotely = new ArrayList(); - ArrayList toGetPlan = new ArrayList(); - ArrayList toSend = new ArrayList(); - + State syncState; // Separate plans by state to give appropriated options to each // addActionChangePlanVehicles(selection, popupMenu); // add appropriatly when multivehicles are // needed for (ExtendedTreeNode extendedTreeNode : selectedNodes) { syncState = (State) extendedTreeNode.getUserInfo().get(NodeInfoKey.SYNC.name()); - + + if (mainVehicleLastPlanId != null && mainVehicleLastPlanId + .equalsIgnoreCase(((NameId) extendedTreeNode.getUserObject()).getIdentification())) { + addForMainVehiclePlan = false; + } + if (syncState != null) { switch (syncState) { case REMOTE: @@ -631,6 +664,7 @@ public void mousePressed(MouseEvent e) { case SYNC: toRemoveRemotely.add((NameId) extendedTreeNode.getUserObject()); toRemoveLocally.add((NameId) extendedTreeNode.getUserObject()); + toGetPlanInfo.add((NameId) extendedTreeNode.getUserObject()); toShare.add((NameId) extendedTreeNode.getUserObject()); break; case NOT_SYNC: @@ -638,11 +672,13 @@ public void mousePressed(MouseEvent e) { toRemoveLocally.add((NameId) extendedTreeNode.getUserObject()); toSend.add((NameId) extendedTreeNode.getUserObject()); toGetPlan.add((NameId) extendedTreeNode.getUserObject()); + toGetPlanInfo.add((NameId) extendedTreeNode.getUserObject()); toShare.add((NameId) extendedTreeNode.getUserObject()); break; case LOCAL: toRemoveLocally.add((NameId) extendedTreeNode.getUserObject()); toSend.add((NameId) extendedTreeNode.getUserObject()); + toGetPlanInfo.add((NameId) extendedTreeNode.getUserObject()); toShare.add((NameId) extendedTreeNode.getUserObject()); break; } @@ -651,6 +687,23 @@ public void mousePressed(MouseEvent e) { NeptusLog.pub().error("The plan " + extendedTreeNode + " has no state."); } } + + if (addForMainVehiclePlan) { + NameId nameId = new NameId() { + @Override + public String getIdentification() { + return mainVehicleLastPlanId; + } + @Override + public String getDisplayName() { + return mainVehicleLastPlanId; + } + }; + toGetPlan.add(nameId); + + toGetPlanInfo.add(nameId); + } + if (!toRemoveRemotely.isEmpty()) addActionRemovePlanRemotely(getConsole(), pdbControl, toRemoveRemotely, popupMenu); if (!toRemoveLocally.isEmpty()) @@ -659,7 +712,7 @@ public void mousePressed(MouseEvent e) { addActionSendPlan(getConsole(), pdbControl, toSend, popupMenu); if (!toGetPlan.isEmpty()) addActionGetRemotePlan(getConsole(), pdbControl, toGetPlan, popupMenu); - if (!toSend.isEmpty() || !toRemoveRemotely.isEmpty() || !toGetPlan.isEmpty()) { + if (!toGetPlanInfo.isEmpty()) { ArrayList toGetInfo = new ArrayList<>(); toGetInfo.addAll(toSend); toGetInfo.addAll(toRemoveRemotely); From 2bc673b54f461a196f7406e83ae6a5c60644a3ce Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 24 Jul 2024 11:01:21 +0100 Subject: [PATCH 30/92] conf/params/caravel: Updated parameters. --- conf/params/caravel.en_US.xml | 141 +++++++++++++++++++++++++++++++++- conf/params/caravel.pt_PT.xml | 141 +++++++++++++++++++++++++++++++++- 2 files changed, 276 insertions(+), 6 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 66fb1c4279..ac5b83475b 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -42,7 +42,7 @@ string developer global - Debug + None None, Debug, Trace, Spew @@ -72,7 +72,7 @@ list:string developer global - abort, dislodge, dive, errors, info, force, cr6, restart, go, help, phone, reboot, sk, start, surface, on, off, sensor, sensors, reports, navstat, adcp, ctd, ecopuck, tblive, optode + abort, errors, info, force, go, help, phone, sk, start @@ -2245,6 +2245,141 @@ Change log file after synchronization
+
+ + Entity Label + string + developer + global + Emergency Monitor + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Execution Frequency + real + developer + global + 1.0 + Hz + Frequency at which task is executed + + + Active - Scope + string + developer + global + idle + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + idle + true + + True to activate task, false otherwise + + + SMS Recipient Number + string + user + global + +351912439480 + + Phone number of the SMS recipient + + + Lost Communications Timeout + real + user + global + 1800 + s + Lost Communications Timeout + 60.0 + + + Transmission Interface + string + developer + global + Iridium + + Desired transmission interface + GSM, Iridium, Both + GSM, Iridium, Both + + + Expiration Time - Abort SMS + integer + developer + global + 30 + s + Abort SMS Timeout + 30.0 + + + Expiration Time - Lost Communications + integer + developer + global + 30 + s + Expiration time of lost communications SMS + 0.0 + +
Entity Label diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index bfda4923ca..01801b2829 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -42,7 +42,7 @@ string developer global - Debug + None None, Debug, Trace, Spew @@ -72,7 +72,7 @@ list:string developer global - abort, dislodge, dive, errors, info, force, cr6, restart, go, help, phone, reboot, sk, start, surface, on, off, sensor, sensors, reports, navstat, adcp, ctd, ecopuck, tblive, optode + abort, errors, info, force, go, help, phone, sk, start @@ -2245,6 +2245,141 @@ Change log file after synchronization
+
+ + Nome da Entidade + string + developer + global + Emergency Monitor + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Frequência de Execução + real + developer + global + 1.0 + Hz + Frequência com que a tarefa é executada + + + Ativa - Escopo + string + developer + global + idle + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + user + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + user + idle + true + + Verdadeiro para ativar tarefa, falso caso contrário + + + Número de Destino de Mensagens SMS + string + user + global + +351912439480 + + Número de telefone do destinatário de mensagens SMS + + + Timeout de Perda de Comunicações + real + user + global + 1800 + s + Timeout de Perda de Comunicações + 60.0 + + + Transmission Interface + string + developer + global + Iridium + + Desired transmission interface + GSM, Iridium, Both + GSM, Iridium, Both + + + Expiration Time - Abort SMS + integer + developer + global + 30 + s + Abort SMS Timeout + 30.0 + + + Expiration Time - Lost Communications + integer + developer + global + 30 + s + Expiration time of lost communications SMS + 0.0 + +
Nome da Entidade From 16cfdeed0911dadb034d2ec64031b514c2e478d6 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 24 Jul 2024 11:01:21 +0100 Subject: [PATCH 31/92] conf/params/caravel: Updated parameters. --- conf/params/caravel.en_US.xml | 141 +++++++++++++++++++++++++++++++++- conf/params/caravel.pt_PT.xml | 141 +++++++++++++++++++++++++++++++++- 2 files changed, 276 insertions(+), 6 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 66fb1c4279..ac5b83475b 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -42,7 +42,7 @@ string developer global - Debug + None None, Debug, Trace, Spew @@ -72,7 +72,7 @@ list:string developer global - abort, dislodge, dive, errors, info, force, cr6, restart, go, help, phone, reboot, sk, start, surface, on, off, sensor, sensors, reports, navstat, adcp, ctd, ecopuck, tblive, optode + abort, errors, info, force, go, help, phone, sk, start @@ -2245,6 +2245,141 @@ Change log file after synchronization
+
+ + Entity Label + string + developer + global + Emergency Monitor + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Execution Frequency + real + developer + global + 1.0 + Hz + Frequency at which task is executed + + + Active - Scope + string + developer + global + idle + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + idle + true + + True to activate task, false otherwise + + + SMS Recipient Number + string + user + global + +351912439480 + + Phone number of the SMS recipient + + + Lost Communications Timeout + real + user + global + 1800 + s + Lost Communications Timeout + 60.0 + + + Transmission Interface + string + developer + global + Iridium + + Desired transmission interface + GSM, Iridium, Both + GSM, Iridium, Both + + + Expiration Time - Abort SMS + integer + developer + global + 30 + s + Abort SMS Timeout + 30.0 + + + Expiration Time - Lost Communications + integer + developer + global + 30 + s + Expiration time of lost communications SMS + 0.0 + +
Entity Label diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index bfda4923ca..01801b2829 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -42,7 +42,7 @@ string developer global - Debug + None None, Debug, Trace, Spew @@ -72,7 +72,7 @@ list:string developer global - abort, dislodge, dive, errors, info, force, cr6, restart, go, help, phone, reboot, sk, start, surface, on, off, sensor, sensors, reports, navstat, adcp, ctd, ecopuck, tblive, optode + abort, errors, info, force, go, help, phone, sk, start @@ -2245,6 +2245,141 @@ Change log file after synchronization
+
+ + Nome da Entidade + string + developer + global + Emergency Monitor + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Frequência de Execução + real + developer + global + 1.0 + Hz + Frequência com que a tarefa é executada + + + Ativa - Escopo + string + developer + global + idle + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + user + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + user + idle + true + + Verdadeiro para ativar tarefa, falso caso contrário + + + Número de Destino de Mensagens SMS + string + user + global + +351912439480 + + Número de telefone do destinatário de mensagens SMS + + + Timeout de Perda de Comunicações + real + user + global + 1800 + s + Timeout de Perda de Comunicações + 60.0 + + + Transmission Interface + string + developer + global + Iridium + + Desired transmission interface + GSM, Iridium, Both + GSM, Iridium, Both + + + Expiration Time - Abort SMS + integer + developer + global + 30 + s + Abort SMS Timeout + 30.0 + + + Expiration Time - Lost Communications + integer + developer + global + 30 + s + Expiration time of lost communications SMS + 0.0 + +
Nome da Entidade From 5b210215b37e1e9bfa9697f87b1c3e870c79af21 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 25 Jul 2024 13:54:03 +0100 Subject: [PATCH 32/92] comm/iridium/HubIridiumMessenger: Avoid potential null pointer and cleanups. --- .../comm/iridium/HubIridiumMessenger.java | 136 ++++++------------ 1 file changed, 46 insertions(+), 90 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java index 1cd8e12667..59151ce24c 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java @@ -83,17 +83,11 @@ public class HubIridiumMessenger implements IridiumMessenger { protected String messagesUrl = serverUrl+"iridium"; protected int timeoutMillis = 10000; protected HashSet listeners = new HashSet<>(); - private static Pattern p = Pattern.compile("\\((.)\\) \\((.*)\\) (.*) / (.*), (.*) / .*"); - private static TimeZone tz = TimeZone.getTimeZone("UTC"); - private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + private static final Pattern p = Pattern.compile("\\((.)\\) \\((.*)\\) (.*) / (.*), (.*) / .*"); + private static final TimeZone tz = TimeZone.getTimeZone("UTC"); + private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); static { dateFormat.setTimeZone(tz); } - // protected Thread t = null; - - // public HubIridiumMessenger() { - // startPolling(); - // } - public DeviceUpdate pollActiveDevices() throws Exception { Gson gson = new Gson(); URL url = new URL(activeSystemsUrl); @@ -108,11 +102,15 @@ public DeviceUpdate pollActiveDevices() throws Exception { for (HubSystemMsg s : sys) { if (s.imcid > Integer.MAX_VALUE) continue; + + Date date = stringToDate(s.updated_at); + if (date == null) + date = new Date(); Position pos = new Position(); pos.id = (int) s.imcid; pos.latRads = s.coordinates[0]; pos.lonRads = s.coordinates[1]; - pos.timestamp = stringToDate(s.updated_at).getTime() / 1000.0; + pos.timestamp = date.getTime() / 1000.0; pos.posType = PosType.Unknown; up.getPositions().put(pos.id, pos); } @@ -120,43 +118,6 @@ public DeviceUpdate pollActiveDevices() throws Exception { return up; } -// public void startPolling() { -// if (t != null) -// stopPolling(); -// t = new Thread("Hub Iridium message updater") { -// @Override -// public void run() { -// Date lastTime = null; -// while (true) { -// try { -// Thread.sleep(60 * 1000); -// -// if (lastTime == null) -// lastTime = new Date(System.currentTimeMillis() - (3600 * 1000)); -// -// Collection newMessages = pollMessages(lastTime); -// lastTime = new Date(); -// -// for (IridiumMessage m : newMessages) -// for (IridiumMessageListener listener : listeners) -// listener.messageReceived(m); -// } -// catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// }; -// t.setDaemon(true); -// t.start(); -// } - -// public void stopPolling() { -// if (t != null) -// t.interrupt(); -// t = null; -// } -// @Override public void addListener(IridiumMessageListener listener) { listeners.add(listener); @@ -184,20 +145,21 @@ public void sendMessage(IridiumMessage msg) throws Exception { conn.setRequestProperty ("Authorization", authKey); } - OutputStream os = conn.getOutputStream(); - os.write(data); - os.close(); + try (OutputStream os = conn.getOutputStream()) { + os.write(data); + } - NeptusLog.pub().info(messagesUrl+" : "+conn.getResponseCode()+" "+conn.getResponseMessage()); + NeptusLog.pub().info("{} : {} {}", messagesUrl, conn.getResponseCode(), conn.getResponseMessage()); - InputStream is = conn.getInputStream(); - ByteArrayOutputStream incoming = new ByteArrayOutputStream(); - IOUtils.copy(is, incoming); - is.close(); - - NeptusLog.pub().info("Sent "+msg.getClass().getSimpleName()+" through HTTP: "+conn.getResponseCode()+" "+conn.getResponseMessage()); - try { - logHubInteraction(msg.getClass().getSimpleName()+" ("+msg.getMessageType()+")", messagesUrl, conn.getRequestMethod(), ""+conn.getResponseCode(), ByteUtil.encodeToHex(msg.serialize()), new String(incoming.toByteArray())); + try (InputStream is = conn.getInputStream(); ByteArrayOutputStream incoming = new ByteArrayOutputStream()) { + IOUtils.copy(is, incoming); + + NeptusLog.pub().info("Sent {} through HTTP: {} {}", msg.getClass().getSimpleName(), + conn.getResponseCode(), conn.getResponseMessage()); + + logHubInteraction(msg.getClass().getSimpleName()+" ("+msg.getMessageType()+")", messagesUrl, + conn.getRequestMethod(), ""+conn.getResponseCode(), ByteUtil.encodeToHex(msg.serialize()), + incoming.toString()); } catch (Exception e) { NeptusLog.pub().error(e); @@ -210,9 +172,9 @@ public void sendMessage(IridiumMessage msg) throws Exception { public synchronized void logHubInteraction(String message, String url, String method, String statusCode, String requestData, String responseData) throws Exception { if (! (new File("log/hub.log")).exists()) { - BufferedWriter tmp = new BufferedWriter(new FileWriter(new File("log/hub.log"), false)); - tmp.write("Time of Day, Message Type, URL, Method, Status Code, Request Data (hex encoded), Response Data\n"); - tmp.close(); + try (BufferedWriter tmp = new BufferedWriter(new FileWriter(new File("log/hub.log"), false))) { + tmp.write("Time of Day, Message Type, URL, Method, Status Code, Request Data (hex encoded), Response Data\n"); + } } BufferedWriter postWriter = new BufferedWriter(new FileWriter(new File("log/hub.log"), true)); @@ -231,15 +193,14 @@ public synchronized void logHubInteraction(String message, String url, String me @Override public Collection pollMessages(Date timeSince) throws Exception { + NeptusLog.pub().info("Polling messages since {}", dateToString(timeSince)); - NeptusLog.pub().info("Polling messages since "+dateToString(timeSince)); - - String since = null; - if (timeSince != null) - since = dateToString(timeSince); - URL u = new URL(messagesUrl+"?since="+(timeSince.getTime()/1000)); - if (since == null) + URL u; + if (timeSince != null) { + u = new URL(messagesUrl + "?since=" + (timeSince.getTime() / 1000)); + } else { u = new URL(messagesUrl); + } HttpURLConnection conn = (HttpURLConnection) u.openConnection(); conn.setDoOutput(true); conn.setRequestMethod( "GET" ); @@ -251,10 +212,12 @@ public Collection pollMessages(Date timeSince) throws Exception ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(conn.getInputStream(), baos); - logHubInteraction("Iridium Poll", u.toString(), conn.getRequestMethod(), ""+conn.getResponseCode(), "", new String(baos.toByteArray())); + logHubInteraction("Iridium Poll", u.toString(), conn.getRequestMethod(), "" + + conn.getResponseCode(), "", baos.toString()); if (conn.getResponseCode() != 200) throw new Exception("Hub iridium server returned "+conn.getResponseCode()+": "+conn.getResponseMessage()); + HubMessage[] msgs = gson.fromJson(baos.toString(), HubMessage[].class); Vector ret = new Vector<>(); @@ -264,7 +227,6 @@ public Collection pollMessages(Date timeSince) throws Exception ret.add(m.message()); } catch (Exception e) { - String report = new String(Hex.decodeHex(m.msg.toCharArray())); Matcher matcher = p.matcher(report); if (matcher.matches()) { @@ -273,8 +235,8 @@ public Collection pollMessages(Date timeSince) throws Exception String latMins = matcher.group(4); String lonMins = matcher.group(5); - String latParts[] = latMins.split(" "); - String lonParts[] = lonMins.split(" "); + String[] latParts = latMins.split(" "); + String[] lonParts = lonMins.split(" "); double lat = getCoords(latParts); double lon = getCoords(lonParts); long timestamp = parseTimeString(timeOfDay).getTime(); @@ -284,8 +246,8 @@ public Collection pollMessages(Date timeSince) throws Exception if (system != null) { system.setLocation(new LocationType(lat, lon), timestamp); } - - NeptusLog.pub().info("Text report: "+report); + + NeptusLog.pub().info("Text report: {}", report); } IridiumCommand msg = new IridiumCommand(); @@ -364,7 +326,6 @@ public Date updatedAt() { } public static class HubSystemMsg { - public long imcid; public String name; public String updated_at; @@ -386,27 +347,22 @@ public void cleanup() { listeners.clear(); //stopPolling(); } - + + @Override + public String toString() { + return getName(); + } + public static void main(String[] args) throws Exception { GeneralPreferences.ripplesUrl = "https://ripples.lsts.pt"; - + HubIridiumMessenger messenger = new HubIridiumMessenger(); Date d = new Date(System.currentTimeMillis() - (1000 * 3600 * 5)); - + System.out.println(dateToString(d)); System.out.println(d.getTime()); Collection msgs = messenger.pollMessages(d); System.out.println(msgs.size()); - msgs.stream().forEach(m -> { - System.out.println(m.asImc()); - }); - - - - } - - @Override - public String toString() { - return getName(); + msgs.forEach(m -> System.out.println(m.asImc())); } } From 39030c332b8c0ff8a66b75c9e4a4dd943b7ce2cd Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 25 Jul 2024 18:50:35 +0100 Subject: [PATCH 33/92] plugins/caravelenv/CaravelDataPlotter: Added filter for accepted data source entities and fix color map painting. --- .../caravelenv/CaravelDataPlotter.java | 68 ++++++++++++++++--- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java index fba8d274f9..6b604e3d4d 100644 --- a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java +++ b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java @@ -49,6 +49,7 @@ import pt.lsts.neptus.colormap.ColorMap; import pt.lsts.neptus.colormap.ColorMapFactory; import pt.lsts.neptus.colormap.ColorMapUtils; +import pt.lsts.neptus.comm.manager.imc.EntitiesResolver; import pt.lsts.neptus.comm.manager.imc.ImcSystem; import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; import pt.lsts.neptus.console.ConsoleLayer; @@ -123,6 +124,23 @@ public class CaravelDataPlotter extends ConsoleLayer implements PreferencesListe @NeptusProperty(name = "Show water current", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Water Current") public boolean showWaterCurrent = false; + @NeptusProperty(name = "Valid temperature data sources", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") + public String validTempDataSources = "CTD, Daemon"; + @NeptusProperty(name = "Valid salinity data sources", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Salinity") + public String validSalDataSources = "CTD, Daemon"; + @NeptusProperty(name = "Valid turbidity data sources", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Turbidity") + public String validTurbidityDataSources = "Fluorometers, Daemon"; + @NeptusProperty(name = "Valid chlorophyll data sources", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Chlorophyll") + public String validChlorophyllDataSources = "Fluorometers, Daemon"; + @NeptusProperty(name = "Valid dissolved organic matter data sources", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Organic Matter") + public String validDissolvedOrganicMatterDataSources = "Fluorometers, Daemon"; + @NeptusProperty(name = "Valid dissolved oxygen data sources", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Dissolved Oxygen") + public String validDissolvedOxygenDataSources = "Dissolved Oxygen, Daemon"; + @NeptusProperty(name = "Valid air saturation data sources", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Air Saturation") + public String validAirSaturationDataSources = "Dissolved Oxygen, Daemon"; + @NeptusProperty(name = "Valid water current data sources", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Water Current") + public String validWaterCurrentDataSources = "ADCP, Daemon"; + @NeptusProperty(name = "Min temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") public double minTemp = 15; @NeptusProperty(name = "Max temperature", userLevel = NeptusProperty.LEVEL.REGULAR, category = "Temperature") @@ -362,6 +380,10 @@ public void on(Temperature msg) { if (!getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { return; } + String entity = EntitiesResolver.resolveName(msg.getSourceName(), (int) msg.getSrcEnt()); + if (entity != null && !validTempDataSources.contains(entity)) { + return; + } extractSensorMeasurementValueFromMessage(msg.getValue(), pointsTemp, msg); offScreenTemperature.triggerImageRebuild(); } @@ -371,6 +393,10 @@ public void on(Salinity msg) { if (!getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { return; } + String entity = EntitiesResolver.resolveName(msg.getSourceName(), (int) msg.getSrcEnt()); + if (entity != null && !validSalDataSources.contains(entity)) { + return; + } extractSensorMeasurementValueFromMessage(msg.getValue(), pointsSalinity, msg); offScreenSalinity.triggerImageRebuild(); } @@ -380,6 +406,10 @@ public void on(Turbidity msg) { if (!getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { return; } + String entity = EntitiesResolver.resolveName(msg.getSourceName(), (int) msg.getSrcEnt()); + if (entity != null && !validTurbidityDataSources.contains(entity)) { + return; + } extractSensorMeasurementValueFromMessage(msg.getValue(), pointsTurbidity, msg); offScreenTurbidity.triggerImageRebuild(); } @@ -389,6 +419,10 @@ public void on(Chlorophyll msg) { if (!getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { return; } + String entity = EntitiesResolver.resolveName(msg.getSourceName(), (int) msg.getSrcEnt()); + if (entity != null && !validChlorophyllDataSources.contains(entity)) { + return; + } extractSensorMeasurementValueFromMessage(msg.getValue(), pointsChlorophyll, msg); offScreenChlorophyll.triggerImageRebuild(); } @@ -398,6 +432,10 @@ public void on(DissolvedOrganicMatter msg) { if (!getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { return; } + String entity = EntitiesResolver.resolveName(msg.getSourceName(), (int) msg.getSrcEnt()); + if (entity != null && !validDissolvedOrganicMatterDataSources.contains(entity)) { + return; + } extractSensorMeasurementValueFromMessage(msg.getValue(), pointsDissolvedOrganicMatter, msg); offScreenDissolvedOrganicMatter.triggerImageRebuild(); } @@ -407,6 +445,10 @@ public void on(DissolvedOxygen msg) { if (!getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { return; } + String entity = EntitiesResolver.resolveName(msg.getSourceName(), (int) msg.getSrcEnt()); + if (entity != null && !validDissolvedOxygenDataSources.contains(entity)) { + return; + } extractSensorMeasurementValueFromMessage(msg.getValue(), pointsDissolvedOxygen, msg); offScreenDissolvedOxygen.triggerImageRebuild(); } @@ -416,6 +458,10 @@ public void on(AirSaturation msg) { if (!getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { return; } + String entity = EntitiesResolver.resolveName(msg.getSourceName(), (int) msg.getSrcEnt()); + if (entity != null && !validAirSaturationDataSources.contains(entity)) { + return; + } extractSensorMeasurementValueFromMessage(msg.getValue(), pointsAirSaturation, msg); offScreenAirSaturation.triggerImageRebuild(); } @@ -425,6 +471,10 @@ public void on(CurrentProfile msg) { if (!getConsole().getMainSystem().equalsIgnoreCase(msg.getSourceName())) { return; } + String entity = EntitiesResolver.resolveName(msg.getSourceName(), (int) msg.getSrcEnt()); + if (entity != null && !validWaterCurrentDataSources.contains(entity)) { + return; + } LocationType loc = getSystemLocation(); double depth = getSystemLocationDepth(); @@ -881,57 +931,57 @@ private static BufferedImage createBufferedImage(int cacheImgWidth, int cacheImg } private void paintColorbars(Graphics2D go, StateRenderer2D renderer) { - int offsetHeight = 130 * 2; + int offsetHeight = 130 * 3; int offsetWidth = 5; int offsetDelta = 130; if (showTemp) { Graphics2D gl = (Graphics2D) go.create(); gl.translate(offsetWidth, offsetHeight); - ColorBarPainterUtil.paintColorBar(go, colormapTemp, "Temperature", "ºC", minTemp, maxTemp); + ColorBarPainterUtil.paintColorBar(gl, colormapTemp, "Temperature", "ºC", minTemp, maxTemp); gl.dispose(); offsetHeight += offsetDelta; } else if (showSal) { Graphics2D gl = (Graphics2D) go.create(); gl.translate(offsetWidth, offsetHeight); - ColorBarPainterUtil.paintColorBar(go, colormapSal, "Salinity", "PSU", minSal, maxSal); + ColorBarPainterUtil.paintColorBar(gl, colormapSal, "Salinity", "PSU", minSal, maxSal); gl.dispose(); offsetHeight += offsetDelta; } else if (showTurbidity) { Graphics2D gl = (Graphics2D) go.create(); gl.translate(offsetWidth, offsetHeight); - ColorBarPainterUtil.paintColorBar(go, colormapTurbidity, "Turbidity", "NTU", minTurbidity, maxTurbidity); + ColorBarPainterUtil.paintColorBar(gl, colormapTurbidity, "Turbidity", "NTU", minTurbidity, maxTurbidity); gl.dispose(); offsetHeight += offsetDelta; } else if (showChlorophyll) { Graphics2D gl = (Graphics2D) go.create(); gl.translate(offsetWidth, offsetHeight); - ColorBarPainterUtil.paintColorBar(go, colormapChlorophyll, "Chlorophyll", "µg/L", minChlorophyll, maxChlorophyll); + ColorBarPainterUtil.paintColorBar(gl, colormapChlorophyll, "Chlorophyll", "µg/L", minChlorophyll, maxChlorophyll); gl.dispose(); offsetHeight += offsetDelta; } else if (showDissolvedOrganicMatter) { Graphics2D gl = (Graphics2D) go.create(); gl.translate(offsetWidth, offsetHeight); - ColorBarPainterUtil.paintColorBar(go, colormapDissolvedOrganicMatter, "Dissolved Organic Matter", "PPB", minDissolvedOrganicMatter, maxDissolvedOrganicMatter); + ColorBarPainterUtil.paintColorBar(gl, colormapDissolvedOrganicMatter, "Dissolved Organic Matter", "PPB", minDissolvedOrganicMatter, maxDissolvedOrganicMatter); gl.dispose(); offsetHeight += offsetDelta; } else if (showDissolvedOxygen) { Graphics2D gl = (Graphics2D) go.create(); gl.translate(offsetWidth, offsetHeight); - ColorBarPainterUtil.paintColorBar(go, colormapDissolvedOxygen, "Dissolved Oxygen", "µM", minDissolvedOxygen, maxDissolvedOxygen); + ColorBarPainterUtil.paintColorBar(gl, colormapDissolvedOxygen, "Dissolved Oxygen", "µM", minDissolvedOxygen, maxDissolvedOxygen); gl.dispose(); offsetHeight += offsetDelta; } else if (showAirSaturation) { Graphics2D gl = (Graphics2D) go.create(); gl.translate(offsetWidth, offsetHeight); - ColorBarPainterUtil.paintColorBar(go, colormapAirSaturation, "Air Saturation", "%", minAirSaturation, maxAirSaturation); + ColorBarPainterUtil.paintColorBar(gl, colormapAirSaturation, "Air Saturation", "%", minAirSaturation, maxAirSaturation); gl.dispose(); offsetHeight += offsetDelta; } else if (showWaterCurrent) { Graphics2D gl = (Graphics2D) go.create(); gl.translate(offsetWidth, offsetHeight); String txtName = String.format("Water Current [%.2f ±%d]", waterCurrentDepth, waterCurrentDepthWindow); - ColorBarPainterUtil.paintColorBar(go, colormapWaterCurrent, txtName, "m/s", minWaterCurrent, maxWaterCurrent); + ColorBarPainterUtil.paintColorBar(gl, colormapWaterCurrent, txtName, "m/s", minWaterCurrent, maxWaterCurrent); gl.dispose(); offsetHeight += offsetDelta; } From 5a3bf014ae164b6850e0a6c515460a8816f051eb Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 29 Jul 2024 14:51:12 +0100 Subject: [PATCH 34/92] comm/manager/imc/EntitiesResolver: Re-added Save to properties file the EntityList values. --- .../comm/manager/imc/EntitiesResolver.java | 65 ++++++++++--------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java b/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java index 90e2d71632..1931284e6c 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/EntitiesResolver.java @@ -42,6 +42,7 @@ import java.io.File; import java.io.IOException; +import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.Map; @@ -52,34 +53,36 @@ public class EntitiesResolver { public static final String ENTITIES_RESOLVER_PROPERTIES_FILE = ".cache/db/entities-resolver.properties"; - //private static PropertiesLoader properties = null; - //static { - // String propertiesFile = ConfigFetch.resolvePathBasedOnConfigFile(ENTITIES_RESOLVER_PROPERTIES_FILE); - // if (!new File(propertiesFile).exists()) { - // String testFile = ConfigFetch.resolvePathBasedOnConfigFile("../" + ENTITIES_RESOLVER_PROPERTIES_FILE); - // if (new File(testFile).exists()) - // propertiesFile = testFile; - // } - // new File(propertiesFile).getParentFile().mkdirs(); - // properties = new PropertiesLoader(propertiesFile, PropertiesLoader.PROPERTIES); + protected static LinkedHashMap> entitiesMap = new LinkedHashMap>(); + public static final int DEFAULT_ENTITY = 255; - // while (properties.keys().hasMoreElements()) { - // String key = properties.keys().nextElement().toString(); - // String value = properties.getProperty(key); - // //setEntities(key, value, false); - // } - //} + private static PropertiesLoader properties = null; - protected static LinkedHashMap> entitiesMap = new LinkedHashMap>(); - public static final int DEFAULT_ENTITY = 255; + static { + String propertiesFile = ConfigFetch.resolvePathBasedOnConfigFile(ENTITIES_RESOLVER_PROPERTIES_FILE); + if (!new File(propertiesFile).exists()) { + String testFile = ConfigFetch.resolvePathBasedOnConfigFile("../" + ENTITIES_RESOLVER_PROPERTIES_FILE); + if (new File(testFile).exists()) + propertiesFile = testFile; + } + new File(propertiesFile).getParentFile().mkdirs(); + properties = new PropertiesLoader(propertiesFile, PropertiesLoader.PROPERTIES); + + Enumeration it = properties.keys(); + while (it.hasMoreElements()) { + String key = it.nextElement().toString(); + String value = properties.getProperty(key); + setEntities(key, value, false); + } + } public static void saveProperties() { - //try { - // properties.store("EntitiesResolver properties"); - //} - //catch (IOException e) { - // NeptusLog.pub().error("saveProperties", e); - //} + try { + properties.store("EntitiesResolver properties"); + } + catch (IOException e) { + NeptusLog.pub().error("saveProperties", e); + } } /** @@ -103,13 +106,13 @@ public static void setEntities(String id, String listAsStr, boolean save) { aliases.put(Integer.parseInt(tlist.get(key)), key); } - //if (save) { - // String old = properties.getProperty(id); - // if (old == null || !old.equals(listAsStr)) { - // properties.setProperty(id, listAsStr); - // saveProperties(); - // } - //} + if (save) { + String old = properties.getProperty(id); + if (old == null || !old.equals(listAsStr)) { + properties.setProperty(id, listAsStr); + saveProperties(); + } + } entitiesMap.put(id, aliases); } From c5406539c784de7e391c60f9ed01e5afd76c113b Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 29 Jul 2024 15:21:54 +0100 Subject: [PATCH 35/92] plugins/remote-actions-extra/RemoteActionsExtra: Saving now the remote actions in file cache. --- .../RemoteActionsExtra.java | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/plugins-dev/remote-actions-extra/src/java/pt/lsts/neptus/plugins/remoteactionsextra/RemoteActionsExtra.java b/plugins-dev/remote-actions-extra/src/java/pt/lsts/neptus/plugins/remoteactionsextra/RemoteActionsExtra.java index 54655c13a8..ac907420c5 100644 --- a/plugins-dev/remote-actions-extra/src/java/pt/lsts/neptus/plugins/remoteactionsextra/RemoteActionsExtra.java +++ b/plugins-dev/remote-actions-extra/src/java/pt/lsts/neptus/plugins/remoteactionsextra/RemoteActionsExtra.java @@ -35,6 +35,7 @@ import com.google.common.eventbus.Subscribe; import net.miginfocom.swing.MigLayout; import pt.lsts.imc.EntityState; +import pt.lsts.imc.IMCMessage; import pt.lsts.imc.RemoteActions; import pt.lsts.imc.RemoteActionsRequest; import pt.lsts.imc.VehicleState; @@ -49,13 +50,18 @@ import pt.lsts.neptus.plugins.Popup; import pt.lsts.neptus.plugins.update.Periodic; import pt.lsts.neptus.util.MathMiscUtils; +import pt.lsts.neptus.util.PropertiesLoader; +import pt.lsts.neptus.util.conf.ConfigFetch; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.SwingConstants; import java.awt.event.KeyEvent; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -68,6 +74,7 @@ description = "This plugin listen for non motion related remote actions and displays its controls.") @Popup(name = "Remote Actions Extra", width = 300, height = 200, pos = Popup.POSITION.BOTTOM, accelerator = KeyEvent.VK_3) public class RemoteActionsExtra extends ConsolePanel implements MainVehicleChangeListener, ConfigurationListener { + public static final String REMOTE_ACTIONS_EXTRA_PROPERTIES_FILE = ".cache/db/remote-actions-extra.properties"; static final boolean DEFAULT_AXIS_DECIMAL_VAL = false; private static final int DECIMAL_HOUSES_FOR_DECIMAL_AXIS = 6; @@ -125,6 +132,44 @@ enum ActionTypeEnum { private final TakeControlMonitor takeControlMonitor; + private static PropertiesLoader properties = null; + static { + String propertiesFile = ConfigFetch.resolvePathBasedOnConfigFile(REMOTE_ACTIONS_EXTRA_PROPERTIES_FILE); + if (!new File(propertiesFile).exists()) { + String testFile = ConfigFetch.resolvePathBasedOnConfigFile("../" + REMOTE_ACTIONS_EXTRA_PROPERTIES_FILE); + if (new File(testFile).exists()) + propertiesFile = testFile; + } + new File(propertiesFile).getParentFile().mkdirs(); + properties = new PropertiesLoader(propertiesFile, PropertiesLoader.PROPERTIES); + + Enumeration it = properties.keys(); + while (it.hasMoreElements()) { + String key = it.nextElement().toString(); + String value = properties.getProperty(key); + setRemoteActionsExtra(key, value, false); + } + } + + private static void saveProperties() { + try { + properties.store("RemoteActionsExtra properties"); + } + catch (IOException e) { + NeptusLog.pub().error("saveProperties", e); + } + } + + private static void setRemoteActionsExtra(String system, String actionsStr, boolean save) { + if (save) { + String old = properties.getProperty(system); + if (old == null || !old.equals(actionsStr)) { + properties.setProperty(system, actionsStr); + saveProperties(); + } + } + } + @NeptusProperty(name = "OBS Entity Name", userLevel = NeptusProperty.LEVEL.ADVANCED, description = "Used to check the state of the OBS take control status.") public String obsEntityName = "OBS Broker"; @@ -213,7 +258,15 @@ private synchronized void resetUIWithActions() { @Subscribe public void on(ConsoleEventMainSystemChange evt) { - configureActions("", DEFAULT_AXIS_DECIMAL_VAL, false); + String actionsString = ""; + try { + if (properties.containsKey(getConsole().getMainSystem())) { + actionsString = (String) properties.get(getConsole().getMainSystem()); + } + } catch (Exception e) { + NeptusLog.pub().error(e.getMessage()); + } + configureActions(actionsString, DEFAULT_AXIS_DECIMAL_VAL, false); takeControlMonitor.on(evt); } @@ -225,6 +278,7 @@ public void on(RemoteActionsRequest msg) { if (msg.getOp() != RemoteActionsRequest.OP.REPORT) return; + setRemoteActionsExtra(msg.getSourceName(), IMCMessage.encodeTupleList(msg.getActions()), true); configureActions(msg.getActions(), DEFAULT_AXIS_DECIMAL_VAL, false); } From 5daf4a5b672de1ec9a4a1cd44ceb46f9fd917a61 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 30 Jul 2024 11:21:25 +0100 Subject: [PATCH 36/92] plugins/remote-actions-extra/RemoteActionsExtra: Fix to on init read the actions for the main system. --- .../RemoteActionsExtra.java | 91 ++++++++++--------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/plugins-dev/remote-actions-extra/src/java/pt/lsts/neptus/plugins/remoteactionsextra/RemoteActionsExtra.java b/plugins-dev/remote-actions-extra/src/java/pt/lsts/neptus/plugins/remoteactionsextra/RemoteActionsExtra.java index ac907420c5..2feeec1eb9 100644 --- a/plugins-dev/remote-actions-extra/src/java/pt/lsts/neptus/plugins/remoteactionsextra/RemoteActionsExtra.java +++ b/plugins-dev/remote-actions-extra/src/java/pt/lsts/neptus/plugins/remoteactionsextra/RemoteActionsExtra.java @@ -186,6 +186,7 @@ public RemoteActionsExtra(ConsoleLayout console, boolean usedInsideAnotherConsol @Override public void initSubPanel() { + updateForMainSystems(); resetUIWithActions(); } @@ -205,48 +206,50 @@ private synchronized void resetUIWithActions() { removeAll(); setLayout(new MigLayout("insets 10px")); - if (extraActionsTypesMap.isEmpty()) { - add(new JLabel("No actions available", SwingConstants.CENTER), "dock center"); - invalidate(); - validate(); - repaint(100); - return; - } + synchronized (extraActionsTypesMap) { + if (extraActionsTypesMap.isEmpty()) { + add(new JLabel("No actions available", SwingConstants.CENTER), "dock center"); + invalidate(); + validate(); + repaint(100); + return; + } - // Let us process the actions list - List> groupedActions = groupActionsBySimilarity(extraActionsTypesMap.keySet(), true); - groupedActions = processActions(groupedActions, 2, false); - - int grpIdx = 0; - for (List grp1 : groupedActions) { - grpIdx++; - String lastAct = grp1.get(grp1.size() - 1); - for (String action : grp1) { - String wrapLay = ""; - if (lastAct.equals(action)) { - wrapLay = "wrap"; - } - switch (extraActionsTypesMap.get(action)) { - case BUTTON: - JButton button = new JButton(action); - button.addActionListener(e -> { - curState.changeButtonActionValue(action, 1); - }); - String lay = "dock center, sg grp" + grpIdx; - lay += ", " + wrapLay; - add(button, lay); - if ("Take Control".equalsIgnoreCase(action)) { - takeControlMonitor.setButton(button); - takeControlMonitor.askedControl(); - } - break; - case AXIS: - // TODO - case SLIDER: - // TODO - case HALF_SLIDER: - // TODO - break; + // Let us process the actions list + List> groupedActions = groupActionsBySimilarity(extraActionsTypesMap.keySet(), true); + groupedActions = processActions(groupedActions, 2, false); + + int grpIdx = 0; + for (List grp1 : groupedActions) { + grpIdx++; + String lastAct = grp1.get(grp1.size() - 1); + for (String action : grp1) { + String wrapLay = ""; + if (lastAct.equals(action)) { + wrapLay = "wrap"; + } + switch (extraActionsTypesMap.get(action)) { + case BUTTON: + JButton button = new JButton(action); + button.addActionListener(e -> { + curState.changeButtonActionValue(action, 1); + }); + String lay = "dock center, sg grp" + grpIdx; + lay += ", " + wrapLay; + add(button, lay); + if ("Take Control".equalsIgnoreCase(action)) { + takeControlMonitor.setButton(button); + takeControlMonitor.askedControl(); + } + break; + case AXIS: + // TODO + case SLIDER: + // TODO + case HALF_SLIDER: + // TODO + break; + } } } } @@ -258,6 +261,11 @@ private synchronized void resetUIWithActions() { @Subscribe public void on(ConsoleEventMainSystemChange evt) { + updateForMainSystems(); + takeControlMonitor.on(evt); + } + + private void updateForMainSystems() { String actionsString = ""; try { if (properties.containsKey(getConsole().getMainSystem())) { @@ -267,7 +275,6 @@ public void on(ConsoleEventMainSystemChange evt) { NeptusLog.pub().error(e.getMessage()); } configureActions(actionsString, DEFAULT_AXIS_DECIMAL_VAL, false); - takeControlMonitor.on(evt); } @Subscribe From 47e83e185289a563a717a97d6f6c360c074ee5bd Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 30 Jul 2024 16:47:32 +0100 Subject: [PATCH 37/92] console/plugins/planning/plandb/PlanDBControl: Now the get/send/delete/clear plan also use the TCP and Iridium msg sending. --- .../planning/plandb/PlanDBControl.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java b/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java index 1bac11c645..bb628cf5d6 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/plandb/PlanDBControl.java @@ -102,7 +102,10 @@ public boolean clearDatabase() { IMCMessage imc_PlanDB = IMCDefinition.getInstance().create("PlanDB", "type", "REQUEST", "op", "CLEAR", "request_id", IMCSendMessageUtils.getNextRequestId()); - return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + //return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + return IMCSendMessageUtils.sendMessage(imc_PlanDB, ImcMsgManager.TRANSPORT_TCP, null, null, + I18n.text("Error sending clear all plans request"), true, "", + true, true, true, remoteSystemId); } public boolean sendPlan(PlanType plan) { @@ -110,13 +113,19 @@ public boolean sendPlan(PlanType plan) { "request_id", IMCSendMessageUtils.getNextRequestId(), "plan_id", plan.getId(), "arg", plan.asIMCPlan(), "info", ""); - return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + //return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + return IMCSendMessageUtils.sendMessage(imc_PlanDB, ImcMsgManager.TRANSPORT_TCP, null, null, + I18n.text("Error sending plan request"), true, "", + true, true, true, remoteSystemId); } public boolean requestPlan(String plan_id) { IMCMessage imc_PlanDB = IMCDefinition.getInstance().create("PlanDB", "type", "REQUEST", "op", "GET", "request_id", IMCSendMessageUtils.getNextRequestId(), "plan_id", plan_id); - return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + //return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + return IMCSendMessageUtils.sendMessage(imc_PlanDB, ImcMsgManager.TRANSPORT_TCP, null, null, + I18n.text("Error sending request plan request"), true, "", + true, true, true, remoteSystemId); } public boolean requestActivePlan() { @@ -136,7 +145,10 @@ public boolean deletePlan(String plan_id) { IMCMessage imc_PlanDB = IMCDefinition.getInstance().create("PlanDB", "type", "REQUEST", "op", "DEL", "request_id", IMCSendMessageUtils.getNextRequestId(), "plan_id", plan_id); NeptusLog.pub().debug("Sending to " + remoteSystemId); - return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + //return ImcMsgManager.getManager().sendMessageToSystem(imc_PlanDB, remoteSystemId); + return IMCSendMessageUtils.sendMessage(imc_PlanDB, ImcMsgManager.TRANSPORT_TCP, null, null, + I18n.text("Error delete plan request"), true, "", + true, true, true, remoteSystemId); } public void updateKnownState(IMCMessage imc_PlanDBState) { From e3b6e48d94ef6f72a90faa4c29743dafe08dbec5 Mon Sep 17 00:00:00 2001 From: xBogas <119903183+xBogas@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:01:14 +0100 Subject: [PATCH 38/92] conf/params/caravel: Updated parameters. --- conf/params/caravel.en_US.xml | 1931 ++++++++++++++++++++++++++++++--- conf/params/caravel.pt_PT.xml | 1931 ++++++++++++++++++++++++++++++--- 2 files changed, 3528 insertions(+), 334 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index ac5b83475b..5a5c327ab3 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -185,7 +185,7 @@ real developer global - 0.25 + 0.75 Percentage of thrust assistance @@ -563,6 +563,15 @@ + + Entity Label - CAS + string + developer + global + Path Control + + Entity label of CAS entity +
@@ -855,7 +864,7 @@ string developer global - GPS Navigation + Simulated Navigation Manager Entity label of 'GpsFix' message @@ -873,7 +882,7 @@ string developer global - + AirMar120WX Entity label of 'AbsoluteWind' message @@ -2099,6 +2108,82 @@ None, Debug, Trace, Spew
+
+ + Entity Label + string + developer + global + CPU Scaling + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Set CPU In Mode + string + developer + global + powersave + + Set CPU In Mode. + + + Use Linux Liquorix + boolean + developer + global + false + + Use Linux Liquorix. + + + Set Maximum CPU Frequency in MHz + integer + developer + global + 500 + + Set Maximum CPU Frequency in MHz. + +
Entity Label @@ -2353,7 +2438,7 @@ string developer global - Iridium + Both Desired transmission interface GSM, Iridium, Both @@ -2443,7 +2528,7 @@ list:string developer global - Daemon, GPS, Navigation, Operational Limits, Path Control + Daemon, GPS, Operational Limits, Path Control Default entities to monitor @@ -2452,7 +2537,7 @@ list:string developer global - Clock, Collisions + Clock, Navigation Manager Additional default entities to monitor in Hardware profile @@ -2674,6 +2759,118 @@ 0.0
+
+ + Entity Label + string + developer + global + Payload Monitor + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + maneuver + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + maneuver + 1 + + True to activate task, false otherwise + + + Payload timeout + real + developer + global + 120 + + Payload timeout in seconds. + + + Payload Messages + list:string + developer + global + + + List of messages <Message>:<Entity> to send using Iridium. + + + Maximum payload size + integer + developer + global + 250 + + Maximum size of iridium payload messages in bytes. + + + Message TTL + integer + developer + global + 120 + + Time to live for iridium messages. + +
Entity Label @@ -2916,7 +3113,7 @@ global GPS - Name of preferred navigation unit. + Name of preferred GPS navigation unit. Secondary unit @@ -2925,7 +3122,7 @@ global CPC - Name of secondary preferred navigation unit. + Name of secondary preferred GPS navigation unit. Third unit @@ -2934,7 +3131,7 @@ global AIS - Name of third preferred navigation unit. + Name of third preferred GPS navigation unit. Convert Height to Geoid Height @@ -3354,7 +3551,7 @@ string developer global - uart:///dev/ttyCPC:115200 + uart:///dev/ttyS2:115200 IO device URI in the form "uart://DEVICE:BAUD" @@ -3570,7 +3767,7 @@ boolean developer global - false + true Power Channel State @@ -3588,7 +3785,7 @@ boolean developer global - false + true Power Channel State @@ -3651,7 +3848,7 @@ string developer global - Private (ECHOTRIP) + ECHOTRIP Power Channel Entity Label @@ -3660,7 +3857,7 @@ boolean developer global - false + true Power Channel State @@ -3669,7 +3866,7 @@ string developer global - Private (OXYGEN) + OXYGEN Power Channel Entity Label @@ -3678,7 +3875,7 @@ boolean developer global - false + true Power Channel State @@ -3687,7 +3884,7 @@ string developer global - Private (AIRMAR) + AIRMAR Power Channel Entity Label @@ -3696,7 +3893,7 @@ boolean developer global - false + true Power Channel State @@ -3705,7 +3902,7 @@ string developer global - Private (CTD_P) + CTD_P Power Channel Entity Label @@ -3714,7 +3911,7 @@ boolean developer global - false + true Power Channel State @@ -3741,7 +3938,7 @@ string developer global - Private (DCP_P) + ADCP_P Power Channel Entity Label @@ -3750,7 +3947,7 @@ boolean developer global - false + true Power Channel State @@ -3795,7 +3992,7 @@ string developer global - Private (MOBILE) + MOBILE Power Channel Entity Label @@ -3804,7 +4001,7 @@ boolean developer global - false + true Power Channel State @@ -3984,7 +4181,7 @@ boolean developer global - false + true Is Main CPU @@ -3998,13 +4195,13 @@ Set CPC to use NAV and Iridium at Boot.
-
+
Entity Label string developer global - GPS + AIS Main entity label @@ -4022,7 +4219,7 @@ integer developer global - 30.0 + 10.0 @@ -4078,39 +4275,9 @@ string developer global - uart:///dev/ttyS10:19200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 10.0 - s - Input timeout - 0.0 - - - Sentence Order - list:string - developer - global - GPGGA, GPROT - - Sentence order - - - Acquisition Frequency - integer - developer - global - 1 + uart:///dev/ttyS10:38400 - Acquisition Frequency - 0 - 5 + Serial port device used to communicate with the sensor Initialization String 0 - Command @@ -4202,35 +4369,1021 @@ - - Initialization String 5 - Command - string + + Sentence Order + list:string developer global - + GPS Sentence order - - Initialization String 5 - Reply - string + + Input Timeout + real developer global - - - + 4.0 + s + Input timeout + 0.0 - - Initialization String 6 - Command - string + + AIS Error - Max + integer developer global - + 3 - + Max erros for Ais messages parser - - Initialization String 6 - Reply + + AIS Error - Interval + real + developer + global + 10.0 + + Invertal for checking AIS errors + + + Power Channel + string + developer + global + + + Power Channel + + + Log messages + boolean + developer + global + false + + Add messages received to logs + +
+
+ + Entity Label + string + developer + global + AirMar120WX + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 3.0 + + + + + Deactivation Time + integer + developer + global + 3.0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS8:4800 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 7.0 + s + Input timeout + 0.0 + + + Angle offset + real + developer + global + 5 + ° + Angle offset for relative wind + +
+
+ + Entity Label + string + developer + global + Fluorometers + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + maneuver + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + maneuver + 1 + + True to activate task, false otherwise + + + Serial Port - Device + string + developer + global + /dev/ttyS11 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 19200 + + Serial port Baud Rate + + + Input Timeout + real + developer + global + 5.0 + s + Amount of seconds to wait for data before reporting an error + 2.0 + + + Device Serial Number + string + developer + global + BBFL2W-8379 + + Device's serial number. Required to check communication with device. + + + CDOM -- Dark Counts + integer + developer + global + 62 + + Signal output of the meter in clean water with black tape over detector + + + CDOM -- Scale Factor + real + developer + global + 0.0916 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Chlorophyll -- Dark Counts + integer + developer + global + 49 + + Signal output of the meter in clean water with black tape over detector + + + Chlorophyll -- Scale Factor + real + developer + global + 0.0073 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Turbidity -- Dark Counts + integer + developer + global + 51 + + Signal output of the meter in clean water with black tape over detector + + + Turbidity -- Scale Factor + real + developer + global + 0.0024 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Sampling Duration + real + user + maneuver + 0.0 + + Sampling duration in seconds + + + Sampling Period + real + user + maneuver + 0.0 + + Sampling period in seconds + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. + +
+
+ + Entity Label + string + developer + global + GPS + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 30.0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS9:19200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 10.0 + s + Input timeout + 0.0 + + + Sentence Order + list:string + developer + global + GPGGA, GPROT + + Sentence order + + + Acquisition Frequency + integer + developer + global + 1 + + Acquisition Frequency + 0 + 5 + + + Initialization String 0 - Command + string + developer + global + + + + + + Initialization String 0 - Reply + string + developer + global + + + + + + Initialization String 1 - Command + string + developer + global + + + + + + Initialization String 1 - Reply + string + developer + global + + + + + + Initialization String 2 - Command + string + developer + global + + + + + + Initialization String 2 - Reply + string + developer + global + + + + + + Initialization String 3 - Command + string + developer + global + + + + + + Initialization String 3 - Reply + string + developer + global + + + + + + Initialization String 4 - Command + string + developer + global + + + + + + Initialization String 4 - Reply + string + developer + global + + + + + + Initialization String 5 - Command + string + developer + global + + + + + + Initialization String 5 - Reply + string + developer + global + + + + + + Initialization String 6 - Command + string + developer + global + + + + + + Initialization String 6 - Reply + string + developer + global + + + + + + Initialization String 7 - Command + string + developer + global + + + + + + Initialization String 7 - Reply + string + developer + global + + + + + + Initialization String 8 - Command + string + developer + global + + + + + + Initialization String 8 - Reply + string + developer + global + + + + + + Initialization String 9 - Command + string + developer + global + + + + + + Initialization String 9 - Reply + string + developer + global + + + + +
+
+ + Entity Label + string + developer + global + AHRS + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 20.0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS4 + + IO device URI in the form "uart://DEVICE".This device has only one baud rate. + + + Power Channel - Name + string + developer + global + + + Name of the power channel + + + Hard-Iron Calibration + list:real + developer + global + 0.0410, -0.0470, 0.0 + G + Hard-Iron calibration parameters + 3 + + + Output Frequency + integer + developer + global + 20 + Hz + Output frequency + 1 + 127 + + + Raw Data + boolean + developer + global + false + + Set to true to enable raw data output + + + Rotation Matrix + list:real + developer + global + 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 + + Rotation matrix which is dependent of the mounting position + 9 + + + Timeout - Error + real + developer + global + 3.0 + s + Number of seconds without data before reporting an error + 1.0 + + + Timeout - Failure + real + developer + global + 6.0 + s + Number of seconds without data before restarting task + 1.0 + + + Last Calibration Time + string + user + global + 2024-05-09 14:04 + + Date of last successful calibration + +
+
+ + Entity Label + string + developer + global + ADCP + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 5 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS6:115200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. + + + Sample Time Duration + integer + user + maneuver + 60 + + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + + Periodicity of Data Sampling in seconds. + + + Initialization String 0 - Command + string + developer + global + SETDEFAULT,ALL + + + + + Initialization String 1 - Command + string + developer + global + SETPLAN,MIAVG=1,AVG=1,DIAVG=0,VD=0,MV=10,SA=35,BURST=1,MIBURST=3600,DIBURST=0,SV=0,FN="RAWDATA.ad2cp",SO=0,FREQ=500,NSTT=0\r\n + + + + + Initialization String 2 - Command + string + developer + global + SETAVG,NC=16,CS=4,BD=1.0,CY="ENU",PL=0,AI=1,VP=0.000,VR=5.0,DF=3,NPING=3,NB=4,CH=0,MUX=0,BW="NARROW",ALTI=1,BT=0,ICE=0,ALTISTART=0.5,ALTIEND=70,RAWALTI=60\r\n + + + + + Initialization String 3 - Command + string + developer + global + SETTMAVG,EN=1,CD=1,PD=1,AVG=1,TV=1,TA=1,TC=1,CY="ENU",FO=0,SO=1,DF=3,DISTILT=0,TPG=1,MAPBINS=0\r\n + + + + + Initialization String 4 - Command + string + developer + global + SETTMALTI,EN=1,TS=1,TQ=1,FO=0,SO=1,DF=200,TPR=0\r\n + + + + + Initialization String 5 - Command + string + developer + global + SETTMBURST,EN=0,NS=1,SO=0,FO=0,DF=3,ENAVG=0,CY="ENU",MAPBINS=0\r\n + + + + + Initialization String 6 - Command + string + developer + global + SETINST,BR=115200,RS=232,LED="ON",ORIENT="ZDOWN",CMTOUT=300,DMTOUT=60,CFMTOUT=60\r\n + + + + + Initialization String 7 - Command + string + developer + global + SAVE,ALL\r\n + + + + + Initialization String 8 - Command + string + developer + global + + + + + + Initialization String 9 - Command string developer global @@ -4238,53 +5391,129 @@ - - Initialization String 7 - Command +
+
+ + Entity Label string developer global - + Dissolved Oxygen + + Main entity label + + + Execution Priority + integer + developer + global + 20 + + Execution priority + + + Activation Time + integer + developer + global + 60 - - Initialization String 7 - Reply - string + + Deactivation Time + integer developer global - + 0 - - Initialization String 8 - Command + + Debug Level string developer global - + None + None, Debug, Trace, Spew + None, Debug, Trace, Spew - - Initialization String 8 - Reply + + Active - Scope string developer global - + global - + Scoped of the 'Active' parameter - - Initialization String 9 - Command + + Active - Visibility string developer global - + developer - + Visibility of the 'Active' parameter - - Initialization String 9 - Reply + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS7:9600 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Measurement String Identifier + string + developer + global + 4835 + + Measurement command string identifier + + + Entity Label - Temperature + string + developer + global + CTD + + Entity label of the CTD + + + Entity Label - Depth + string + developer + global + CTD + + Entity label of the CTD + + + Entity Label - Salinity + string + developer + global + CTD + + Entity label of the CTD + + + Power Channel - Name string developer global @@ -4292,14 +5521,59 @@ + + Data rate + real + developer + global + 1 + Hz + Data Acquisition Rate. + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. + + + Sample Time Duration + integer + user + maneuver + 60 + s + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + s + Periodicity of Data Sampling in seconds. + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + s + Timeout Transmitting Iridium Message. +
-
+
Entity Label string developer global - AHRS + CTD Main entity label @@ -4317,7 +5591,7 @@ integer developer global - 20.0 + 10.0 @@ -4346,7 +5620,7 @@ string developer global - global + maneuver Scoped of the 'Active' parameter @@ -4355,15 +5629,15 @@ string developer global - developer + user Visibility of the 'Active' parameter Active boolean - developer - global + user + maneuver 1 True to activate task, false otherwise @@ -4373,9 +5647,45 @@ string developer global - uart:///dev/ttyS9 + uart:///dev/ttyS5:115200 - IO device URI in the form "uart://DEVICE".This device has only one baud rate. + IO device URI in the form "uart://DEVICE:BAUD" + + + Sample Period (ms) + integer + user + global + 125 + ms + Sample period in milliseconds + + + Sample Time Duration + integer + user + maneuver + 5 + + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 20 + + Periodicity of Data Sampling in seconds. + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. Power Channel - Name @@ -4384,85 +5694,101 @@ global - Name of the power channel + Power channel name for the device. Set to empty to disable. - - Hard-Iron Calibration - list:real + + Input Timeout + real developer global - 0.0, 0.0, 0.0 - G - Hard-Iron calibration parameters - 3 + 60 + + Input timeout in seconds. Must be greater than 2*Sample Time Duration - - Output Frequency +
+
+ + Entity Label + string + developer + global + Thermal Zone + + Main entity label + + + Execution Priority integer developer global - 20 - Hz - Output frequency - 1 - 127 + 10 + + Execution priority - - Raw Data - boolean + + Activation Time + integer developer global - false + 0 - Set to true to enable raw data output + - - Rotation Matrix - list:real + + Deactivation Time + integer developer global - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 + 0 - Rotation matrix which is dependent of the mounting position - 9 + - - Timeout - Error - real + + Debug Level + string developer global - 3.0 - s - Number of seconds without data before reporting an error - 1.0 + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew - - Timeout - Failure + + Execution Frequency real developer global - 6.0 - s - Number of seconds without data before restarting task - 1.0 + 1 + Hz + Frequency at which task is executed + + + Path + string + developer + global + /sys/class/thermal/thermal_zone0/temp + + Path to the sysfs file - - Last Calibration Time + + Entity Label - Temperature string - user + developer global - N/A + Mainboard (Core) - Date of last successful calibration + Entity label of temperature sensor
-
+
Entity Label string developer global - Thermal Zone + Autonaut Supervisor Main entity label @@ -4509,27 +5835,29 @@ real developer global - 1 + 2 Hz Frequency at which task is executed - - Path - string + + Loiter On Service -- Radius + real developer global - /sys/class/thermal/thermal_zone0/temp + 30.0 - Path to the sysfs file + Radius for loiter on service option + 5.0 - - Entity Label - Temperature - string + + Loiter On Service -- Speed + real developer global - Mainboard (Core) + 0.5 - Entity label of temperature sensor + Speed for loiter on service option + 0.1
@@ -5310,6 +6638,145 @@ Maximum amount of seconds to wait for missing fragments in incoming messages
+
+ + Entity Label + string + developer + global + GSM + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 10 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Serial Port - Device + string + developer + global + /dev/ttyUSB3 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 115200 + + Serial port baud rate + + + Reply Timeout + real + developer + global + 2.0 + s + Amount of time to wait for a command reply + + + PIN + string + developer + global + + + PIN Code + + + RSSI Periodicity + real + developer + global + 10 + s + Periodicity of RSSI reports + + + Read SMS Periodicity + real + developer + global + 10 + s + Periodicity of received SMS checks + + + SMS Send Timeout + real + developer + global + 60 + s + Maximum amount of time to wait for SMS send completion + + + USSD code + integer + developer + global + 111 + + USSD code + + + Request Balance + boolean + user + global + false + + Enable Balance Request + + + Balance Periodicity + integer + developer + global + 60 + + Balance Periodicity + +
Entity Label @@ -5498,6 +6965,136 @@ Text messages received via Iridium will be tagged with this origin
+
+ + Entity Label + string + developer + global + Iridium Operation + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + global + 0 + + True to activate task, false otherwise + + + Maximum iridium payload size + integer + developer + global + 250 + + Maximum size of iridium payload messages in bytes. + + + Rate Limiters + list:string + developer + global + PlanControlState:120, EstimatedState:120, VehicleState:120, StateReport:120, FuelLevel:120 + + List of <Message>:<Period> to send messages at a specific period. + + + Filtered Entities + list:string + developer + global + + + List of <Message>:<Entity>+<Entity> that define the source entities allowed to pass message of a specific message type. + + + Transport + list:string + developer + global + PlanControl, PlanControlState, EstimatedState, VehicleState, StateReport, FuelLevel, Aborted + + List of messages to transport + + + Message TTL + integer + developer + global + 120 + + Time to live for iridium messages. + + + Iridium Operation Timeout + integer + developer + global + 600 + + Iridium operation timeout in seconds. + +
Entity Label @@ -5578,7 +7175,7 @@ string developer global - /dev/ttyS8 + /dev/ttyS3 Serial port device used to communicate with the modem @@ -5925,7 +7522,7 @@ list:string developer global - Distance:Altimeter+DVL Filtered+Echo Sounder + Distance:Altimeter+DVL Filtered+Echo Sounder, DevDataText:AIS List of <Message>:<Entity>+<Entity> that define the source entities allowed to pass message of a specific message type. @@ -5961,7 +7558,7 @@ list:string developer global - Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation, AisInfo, RemoteSensorInfo, DevDataText List of messages to transport diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index 01801b2829..7960bb4988 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -185,7 +185,7 @@ real developer global - 0.25 + 0.75 Percentage of thrust assistance @@ -563,6 +563,15 @@ + + Entity Label - CAS + string + developer + global + Path Control + + Entity label of CAS entity +
@@ -855,7 +864,7 @@ string developer global - GPS Navigation + Simulated Navigation Manager Entity label of 'GpsFix' message @@ -873,7 +882,7 @@ string developer global - + AirMar120WX Entity label of 'AbsoluteWind' message @@ -2099,6 +2108,82 @@ None, Debug, Trace, Spew
+
+ + Nome da Entidade + string + developer + global + CPU Scaling + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Set CPU In Mode + string + developer + global + powersave + + Set CPU In Mode. + + + Use Linux Liquorix + boolean + developer + global + false + + Use Linux Liquorix. + + + Set Maximum CPU Frequency in MHz + integer + developer + global + 500 + + Set Maximum CPU Frequency in MHz. + +
Nome da Entidade @@ -2353,7 +2438,7 @@ string developer global - Iridium + Both Desired transmission interface GSM, Iridium, Both @@ -2443,7 +2528,7 @@ list:string developer global - Daemon, GPS, Navigation, Operational Limits, Path Control + Daemon, GPS, Operational Limits, Path Control Default entities to monitor @@ -2452,7 +2537,7 @@ list:string developer global - Clock, Collisions + Clock, Navigation Manager Additional default entities to monitor in Hardware profile @@ -2674,6 +2759,118 @@ 0.0
+
+ + Nome da Entidade + string + developer + global + Payload Monitor + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Ativa - Escopo + string + developer + global + maneuver + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + user + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + user + maneuver + 1 + + Verdadeiro para ativar tarefa, falso caso contrário + + + Payload timeout + real + developer + global + 120 + + Payload timeout in seconds. + + + Payload Messages + list:string + developer + global + + + List of messages <Message>:<Entity> to send using Iridium. + + + Maximum payload size + integer + developer + global + 250 + + Maximum size of iridium payload messages in bytes. + + + Message TTL + integer + developer + global + 120 + + Time to live for iridium messages. + +
Nome da Entidade @@ -2916,7 +3113,7 @@ global GPS - Name of preferred navigation unit. + Name of preferred GPS navigation unit. Secondary unit @@ -2925,7 +3122,7 @@ global CPC - Name of secondary preferred navigation unit. + Name of secondary preferred GPS navigation unit. Third unit @@ -2934,7 +3131,7 @@ global AIS - Name of third preferred navigation unit. + Name of third preferred GPS navigation unit. Convert Height to Geoid Height @@ -3354,7 +3551,7 @@ string developer global - uart:///dev/ttyCPC:115200 + uart:///dev/ttyS2:115200 IO device URI in the form "uart://DEVICE:BAUD" @@ -3570,7 +3767,7 @@ boolean developer global - false + true Power Channel State @@ -3588,7 +3785,7 @@ boolean developer global - false + true Power Channel State @@ -3651,7 +3848,7 @@ string developer global - Private (ECHOTRIP) + ECHOTRIP Power Channel Entity Label @@ -3660,7 +3857,7 @@ boolean developer global - false + true Power Channel State @@ -3669,7 +3866,7 @@ string developer global - Private (OXYGEN) + OXYGEN Power Channel Entity Label @@ -3678,7 +3875,7 @@ boolean developer global - false + true Power Channel State @@ -3687,7 +3884,7 @@ string developer global - Private (AIRMAR) + AIRMAR Power Channel Entity Label @@ -3696,7 +3893,7 @@ boolean developer global - false + true Power Channel State @@ -3705,7 +3902,7 @@ string developer global - Private (CTD_P) + CTD_P Power Channel Entity Label @@ -3714,7 +3911,7 @@ boolean developer global - false + true Power Channel State @@ -3741,7 +3938,7 @@ string developer global - Private (DCP_P) + ADCP_P Power Channel Entity Label @@ -3750,7 +3947,7 @@ boolean developer global - false + true Power Channel State @@ -3795,7 +3992,7 @@ string developer global - Private (MOBILE) + MOBILE Power Channel Entity Label @@ -3804,7 +4001,7 @@ boolean developer global - false + true Power Channel State @@ -3984,7 +4181,7 @@ boolean developer global - false + true Is Main CPU @@ -3998,13 +4195,13 @@ Set CPC to use NAV and Iridium at Boot.
-
+
Nome da Entidade string developer global - GPS + AIS Nome principal da entidade @@ -4022,7 +4219,7 @@ integer developer global - 30.0 + 10.0 @@ -4078,39 +4275,9 @@ string developer global - uart:///dev/ttyS10:19200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 10.0 - s - Input timeout - 0.0 - - - Sentence Order - list:string - developer - global - GPGGA, GPROT - - Sentence order - - - Acquisition Frequency - integer - developer - global - 1 + uart:///dev/ttyS10:38400 - Acquisition Frequency - 0 - 5 + Serial port device used to communicate with the sensor Initialization String 0 - Command @@ -4202,35 +4369,1021 @@ - - Initialization String 5 - Command - string + + Sentence Order + list:string developer global - + GPS Sentence order - - Initialization String 5 - Reply - string + + Input Timeout + real developer global - - - + 4.0 + s + Input timeout + 0.0 - - Initialization String 6 - Command - string + + AIS Error - Max + integer developer global - + 3 - + Max erros for Ais messages parser - - Initialization String 6 - Reply + + AIS Error - Interval + real + developer + global + 10.0 + + Invertal for checking AIS errors + + + Power Channel + string + developer + global + + + Power Channel + + + Log messages + boolean + developer + global + false + + Add messages received to logs + +
+
+ + Nome da Entidade + string + developer + global + AirMar120WX + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 3.0 + + + + + Tempo de Desativação + integer + developer + global + 3.0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Ativa - Escopo + string + developer + global + global + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + developer + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + developer + global + 1 + + Verdadeiro para ativar tarefa, falso caso contrário + + + IO Port - Device + string + developer + global + uart:///dev/ttyS8:4800 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 7.0 + s + Input timeout + 0.0 + + + Angle offset + real + developer + global + 5 + ° + Angle offset for relative wind + +
+
+ + Nome da Entidade + string + developer + global + Fluorometers + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Ativa - Escopo + string + developer + global + maneuver + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + user + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + user + maneuver + 1 + + Verdadeiro para ativar tarefa, falso caso contrário + + + Serial Port - Device + string + developer + global + /dev/ttyS11 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 19200 + + Serial port Baud Rate + + + Input Timeout + real + developer + global + 5.0 + s + Amount of seconds to wait for data before reporting an error + 2.0 + + + Device Serial Number + string + developer + global + BBFL2W-8379 + + Device's serial number. Required to check communication with device. + + + CDOM -- Dark Counts + integer + developer + global + 62 + + Signal output of the meter in clean water with black tape over detector + + + CDOM -- Scale Factor + real + developer + global + 0.0916 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Chlorophyll -- Dark Counts + integer + developer + global + 49 + + Signal output of the meter in clean water with black tape over detector + + + Chlorophyll -- Scale Factor + real + developer + global + 0.0073 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Turbidity -- Dark Counts + integer + developer + global + 51 + + Signal output of the meter in clean water with black tape over detector + + + Turbidity -- Scale Factor + real + developer + global + 0.0024 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Sampling Duration + real + user + maneuver + 0.0 + + Sampling duration in seconds + + + Sampling Period + real + user + maneuver + 0.0 + + Sampling period in seconds + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. + +
+
+ + Nome da Entidade + string + developer + global + GPS + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 30.0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Ativa - Escopo + string + developer + global + global + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + developer + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + developer + global + 1 + + Verdadeiro para ativar tarefa, falso caso contrário + + + IO Port - Device + string + developer + global + uart:///dev/ttyS9:19200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 10.0 + s + Input timeout + 0.0 + + + Sentence Order + list:string + developer + global + GPGGA, GPROT + + Sentence order + + + Acquisition Frequency + integer + developer + global + 1 + + Acquisition Frequency + 0 + 5 + + + Initialization String 0 - Command + string + developer + global + + + + + + Initialization String 0 - Reply + string + developer + global + + + + + + Initialization String 1 - Command + string + developer + global + + + + + + Initialization String 1 - Reply + string + developer + global + + + + + + Initialization String 2 - Command + string + developer + global + + + + + + Initialization String 2 - Reply + string + developer + global + + + + + + Initialization String 3 - Command + string + developer + global + + + + + + Initialization String 3 - Reply + string + developer + global + + + + + + Initialization String 4 - Command + string + developer + global + + + + + + Initialization String 4 - Reply + string + developer + global + + + + + + Initialization String 5 - Command + string + developer + global + + + + + + Initialization String 5 - Reply + string + developer + global + + + + + + Initialization String 6 - Command + string + developer + global + + + + + + Initialization String 6 - Reply + string + developer + global + + + + + + Initialization String 7 - Command + string + developer + global + + + + + + Initialization String 7 - Reply + string + developer + global + + + + + + Initialization String 8 - Command + string + developer + global + + + + + + Initialization String 8 - Reply + string + developer + global + + + + + + Initialization String 9 - Command + string + developer + global + + + + + + Initialization String 9 - Reply + string + developer + global + + + + +
+
+ + Nome da Entidade + string + developer + global + AHRS + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 20.0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Ativa - Escopo + string + developer + global + global + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + developer + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + developer + global + 1 + + Verdadeiro para ativar tarefa, falso caso contrário + + + IO Port - Device + string + developer + global + uart:///dev/ttyS4 + + IO device URI in the form "uart://DEVICE".This device has only one baud rate. + + + Power Channel - Name + string + developer + global + + + Name of the power channel + + + Hard-Iron Calibration + list:real + developer + global + 0.0410, -0.0470, 0.0 + G + Hard-Iron calibration parameters + 3 + + + Output Frequency + integer + developer + global + 20 + Hz + Output frequency + 1 + 127 + + + Raw Data + boolean + developer + global + false + + Set to true to enable raw data output + + + Rotation Matrix + list:real + developer + global + 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 + + Rotation matrix which is dependent of the mounting position + 9 + + + Timeout - Error + real + developer + global + 3.0 + s + Number of seconds without data before reporting an error + 1.0 + + + Timeout - Failure + real + developer + global + 6.0 + s + Number of seconds without data before restarting task + 1.0 + + + Last Calibration Time + string + user + global + 2024-05-09 14:04 + + Date of last successful calibration + +
+
+ + Nome da Entidade + string + developer + global + ADCP + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 5 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Ativa - Escopo + string + developer + global + global + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + developer + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + developer + global + 1 + + Verdadeiro para ativar tarefa, falso caso contrário + + + IO Port - Device + string + developer + global + uart:///dev/ttyS6:115200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. + + + Sample Time Duration + integer + user + maneuver + 60 + + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + + Periodicity of Data Sampling in seconds. + + + Initialization String 0 - Command + string + developer + global + SETDEFAULT,ALL + + + + + Initialization String 1 - Command + string + developer + global + SETPLAN,MIAVG=1,AVG=1,DIAVG=0,VD=0,MV=10,SA=35,BURST=1,MIBURST=3600,DIBURST=0,SV=0,FN="RAWDATA.ad2cp",SO=0,FREQ=500,NSTT=0\r\n + + + + + Initialization String 2 - Command + string + developer + global + SETAVG,NC=16,CS=4,BD=1.0,CY="ENU",PL=0,AI=1,VP=0.000,VR=5.0,DF=3,NPING=3,NB=4,CH=0,MUX=0,BW="NARROW",ALTI=1,BT=0,ICE=0,ALTISTART=0.5,ALTIEND=70,RAWALTI=60\r\n + + + + + Initialization String 3 - Command + string + developer + global + SETTMAVG,EN=1,CD=1,PD=1,AVG=1,TV=1,TA=1,TC=1,CY="ENU",FO=0,SO=1,DF=3,DISTILT=0,TPG=1,MAPBINS=0\r\n + + + + + Initialization String 4 - Command + string + developer + global + SETTMALTI,EN=1,TS=1,TQ=1,FO=0,SO=1,DF=200,TPR=0\r\n + + + + + Initialization String 5 - Command + string + developer + global + SETTMBURST,EN=0,NS=1,SO=0,FO=0,DF=3,ENAVG=0,CY="ENU",MAPBINS=0\r\n + + + + + Initialization String 6 - Command + string + developer + global + SETINST,BR=115200,RS=232,LED="ON",ORIENT="ZDOWN",CMTOUT=300,DMTOUT=60,CFMTOUT=60\r\n + + + + + Initialization String 7 - Command + string + developer + global + SAVE,ALL\r\n + + + + + Initialization String 8 - Command + string + developer + global + + + + + + Initialization String 9 - Command string developer global @@ -4238,53 +5391,129 @@ - - Initialization String 7 - Command +
+
+ + Nome da Entidade string developer global - + Dissolved Oxygen + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 20 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 60 - - Initialization String 7 - Reply - string + + Tempo de Desativação + integer developer global - + 0 - - Initialization String 8 - Command + + Nível de Depuração string developer global - + None + None, Debug, Trace, Spew + None, Debug, Trace, Spew - - Initialization String 8 - Reply + + Ativa - Escopo string developer global - + global - + Escopo do parâmetro 'Ativa' - - Initialization String 9 - Command + + Ativa - Visibilidade string developer global - + developer - + Visibilidade do parâmetro 'Ativa' - - Initialization String 9 - Reply + + Ativa + boolean + developer + global + 1 + + Verdadeiro para ativar tarefa, falso caso contrário + + + IO Port - Device + string + developer + global + uart:///dev/ttyS7:9600 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Measurement String Identifier + string + developer + global + 4835 + + Measurement command string identifier + + + Entity Label - Temperature + string + developer + global + CTD + + Entity label of the CTD + + + Entity Label - Depth + string + developer + global + CTD + + Entity label of the CTD + + + Entity Label - Salinity + string + developer + global + CTD + + Entity label of the CTD + + + Power Channel - Name string developer global @@ -4292,14 +5521,59 @@ + + Data rate + real + developer + global + 1 + Hz + Data Acquisition Rate. + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. + + + Sample Time Duration + integer + user + maneuver + 60 + s + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + s + Periodicity of Data Sampling in seconds. + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + s + Timeout Transmitting Iridium Message. +
-
+
Nome da Entidade string developer global - AHRS + CTD Nome principal da entidade @@ -4317,7 +5591,7 @@ integer developer global - 20.0 + 10.0 @@ -4346,7 +5620,7 @@ string developer global - global + maneuver Escopo do parâmetro 'Ativa' @@ -4355,15 +5629,15 @@ string developer global - developer + user Visibilidade do parâmetro 'Ativa' Ativa boolean - developer - global + user + maneuver 1 Verdadeiro para ativar tarefa, falso caso contrário @@ -4373,9 +5647,45 @@ string developer global - uart:///dev/ttyS9 + uart:///dev/ttyS5:115200 - IO device URI in the form "uart://DEVICE".This device has only one baud rate. + IO device URI in the form "uart://DEVICE:BAUD" + + + Sample Period (ms) + integer + user + global + 125 + ms + Sample period in milliseconds + + + Sample Time Duration + integer + user + maneuver + 5 + + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 20 + + Periodicity of Data Sampling in seconds. + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. Power Channel - Name @@ -4384,85 +5694,101 @@ global - Name of the power channel + Power channel name for the device. Set to empty to disable. - - Hard-Iron Calibration - list:real + + Input Timeout + real developer global - 0.0, 0.0, 0.0 - G - Hard-Iron calibration parameters - 3 + 60 + + Input timeout in seconds. Must be greater than 2*Sample Time Duration - - Output Frequency +
+
+ + Nome da Entidade + string + developer + global + Thermal Zone + + Nome principal da entidade + + + Prioridade de Execução integer developer global - 20 - Hz - Output frequency - 1 - 127 + 10 + + Prioridade de execução - - Raw Data - boolean + + Tempo de Ativação + integer developer global - false + 0 - Set to true to enable raw data output + - - Rotation Matrix - list:real + + Tempo de Desativação + integer developer global - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 + 0 - Rotation matrix which is dependent of the mounting position - 9 + - - Timeout - Error - real + + Nível de Depuração + string developer global - 3.0 - s - Number of seconds without data before reporting an error - 1.0 + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew - - Timeout - Failure + + Frequência de Execução real developer global - 6.0 - s - Number of seconds without data before restarting task - 1.0 + 1 + Hz + Frequência com que a tarefa é executada + + + Path + string + developer + global + /sys/class/thermal/thermal_zone0/temp + + Path to the sysfs file - - Last Calibration Time + + Entity Label - Temperature string - user + developer global - N/A + Mainboard (Core) - Date of last successful calibration + Entity label of temperature sensor
-
+
Nome da Entidade string developer global - Thermal Zone + Autonaut Supervisor Nome principal da entidade @@ -4509,27 +5835,29 @@ real developer global - 1 + 2 Hz Frequência com que a tarefa é executada - - Path - string + + Loiter On Service -- Radius + real developer global - /sys/class/thermal/thermal_zone0/temp + 30.0 - Path to the sysfs file + Radius for loiter on service option + 5.0 - - Entity Label - Temperature - string + + Loiter On Service -- Speed + real developer global - Mainboard (Core) + 0.5 - Entity label of temperature sensor + Speed for loiter on service option + 0.1
@@ -5310,6 +6638,145 @@ Maximum amount of seconds to wait for missing fragments in incoming messages
+
+ + Nome da Entidade + string + developer + global + GSM + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 10 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Serial Port - Device + string + developer + global + /dev/ttyUSB3 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 115200 + + Serial port baud rate + + + Reply Timeout + real + developer + global + 2.0 + s + Amount of time to wait for a command reply + + + PIN + string + developer + global + + + PIN Code + + + RSSI Periodicity + real + developer + global + 10 + s + Periodicity of RSSI reports + + + Read SMS Periodicity + real + developer + global + 10 + s + Periodicity of received SMS checks + + + SMS Send Timeout + real + developer + global + 60 + s + Maximum amount of time to wait for SMS send completion + + + USSD code + integer + developer + global + 111 + + USSD code + + + Request Balance + boolean + user + global + false + + Enable Balance Request + + + Balance Periodicity + integer + developer + global + 60 + + Balance Periodicity + +
Nome da Entidade @@ -5498,6 +6965,136 @@ Text messages received via Iridium will be tagged with this origin
+
+ + Nome da Entidade + string + developer + global + Iridium Operation + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Ativa - Escopo + string + developer + global + global + + Escopo do parâmetro 'Ativa' + + + Ativa - Visibilidade + string + developer + global + user + + Visibilidade do parâmetro 'Ativa' + + + Ativa + boolean + user + global + 0 + + Verdadeiro para ativar tarefa, falso caso contrário + + + Maximum iridium payload size + integer + developer + global + 250 + + Maximum size of iridium payload messages in bytes. + + + Rate Limiters + list:string + developer + global + PlanControlState:120, EstimatedState:120, VehicleState:120, StateReport:120, FuelLevel:120 + + List of <Message>:<Period> to send messages at a specific period. + + + Filtered Entities + list:string + developer + global + + + List of <Message>:<Entity>+<Entity> that define the source entities allowed to pass message of a specific message type. + + + Transport + list:string + developer + global + PlanControl, PlanControlState, EstimatedState, VehicleState, StateReport, FuelLevel, Aborted + + List of messages to transport + + + Message TTL + integer + developer + global + 120 + + Time to live for iridium messages. + + + Iridium Operation Timeout + integer + developer + global + 600 + + Iridium operation timeout in seconds. + +
Nome da Entidade @@ -5578,7 +7175,7 @@ string developer global - /dev/ttyS8 + /dev/ttyS3 Serial port device used to communicate with the modem @@ -5925,7 +7522,7 @@ list:string developer global - Distance:Altimeter+DVL Filtered+Echo Sounder + Distance:Altimeter+DVL Filtered+Echo Sounder, DevDataText:AIS List of <Message>:<Entity>+<Entity> that define the source entities allowed to pass message of a specific message type. @@ -5961,7 +7558,7 @@ list:string developer global - Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation, AisInfo, RemoteSensorInfo, DevDataText List of messages to transport From 5f198415c9c27878b212933b8a2d83c7bc973688 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 1 Aug 2024 14:05:29 +0100 Subject: [PATCH 39/92] conf/params/caravel: Updated parameters. --- conf/params/caravel.en_US.xml | 1933 +++++++++++++++++++++--- conf/params/caravel.pt_PT.xml | 2631 ++++++++++++++++++++++++++------- 2 files changed, 3879 insertions(+), 685 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index ac5b83475b..4bef2d036e 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -185,7 +185,7 @@ real developer global - 0.25 + 0.75 Percentage of thrust assistance @@ -563,6 +563,15 @@ + + Entity Label - CAS + string + developer + global + Path Control + + Entity label of CAS entity +
@@ -855,7 +864,7 @@ string developer global - GPS Navigation + Simulated Navigation Manager Entity label of 'GpsFix' message @@ -873,7 +882,7 @@ string developer global - + AirMar120WX Entity label of 'AbsoluteWind' message @@ -2099,6 +2108,82 @@ None, Debug, Trace, Spew
+
+ + Entity Label + string + developer + global + CPU Scaling + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Set CPU In Mode + string + developer + global + powersave + + Set CPU In Mode. + + + Use Linux Liquorix + boolean + developer + global + false + + Use Linux Liquorix. + + + Set Maximum CPU Frequency in MHz + integer + developer + global + 500 + + Set Maximum CPU Frequency in MHz. + +
Entity Label @@ -2353,7 +2438,7 @@ string developer global - Iridium + Both Desired transmission interface GSM, Iridium, Both @@ -2443,7 +2528,7 @@ list:string developer global - Daemon, GPS, Navigation, Operational Limits, Path Control + Daemon, GPS, Operational Limits, Path Control Default entities to monitor @@ -2452,7 +2537,7 @@ list:string developer global - Clock, Collisions + Clock, Navigation Manager Additional default entities to monitor in Hardware profile @@ -2674,6 +2759,118 @@ 0.0
+
+ + Entity Label + string + developer + global + Payload Monitor + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + maneuver + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + maneuver + 1 + + True to activate task, false otherwise + + + Payload timeout + real + developer + global + 120 + + Payload timeout in seconds. + + + Payload Messages + list:string + developer + global + EstimatedState:Navigation Manager, Temperature:CTD, Temperature:AirMar120WX, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager + + List of messages <Message>:<Entity> to send using Iridium. + + + Maximum payload size + integer + developer + global + 250 + + Maximum size of iridium payload messages in bytes. + + + Message TTL + integer + developer + global + 120 + + Time to live for iridium messages. + +
Entity Label @@ -2916,7 +3113,7 @@ global GPS - Name of preferred navigation unit. + Name of preferred GPS navigation unit. Secondary unit @@ -2925,7 +3122,7 @@ global CPC - Name of secondary preferred navigation unit. + Name of secondary preferred GPS navigation unit. Third unit @@ -2934,7 +3131,7 @@ global AIS - Name of third preferred navigation unit. + Name of third preferred GPS navigation unit. Convert Height to Geoid Height @@ -3354,7 +3551,7 @@ string developer global - uart:///dev/ttyCPC:115200 + uart:///dev/ttyS2:115200 IO device URI in the form "uart://DEVICE:BAUD" @@ -3570,7 +3767,7 @@ boolean developer global - false + true Power Channel State @@ -3588,7 +3785,7 @@ boolean developer global - false + true Power Channel State @@ -3651,7 +3848,7 @@ string developer global - Private (ECHOTRIP) + ECHOTRIP Power Channel Entity Label @@ -3660,7 +3857,7 @@ boolean developer global - false + true Power Channel State @@ -3669,7 +3866,7 @@ string developer global - Private (OXYGEN) + OXYGEN Power Channel Entity Label @@ -3678,7 +3875,7 @@ boolean developer global - false + true Power Channel State @@ -3687,7 +3884,7 @@ string developer global - Private (AIRMAR) + AIRMAR Power Channel Entity Label @@ -3696,7 +3893,7 @@ boolean developer global - false + true Power Channel State @@ -3705,7 +3902,7 @@ string developer global - Private (CTD_P) + CTD_P Power Channel Entity Label @@ -3714,7 +3911,7 @@ boolean developer global - false + true Power Channel State @@ -3741,7 +3938,7 @@ string developer global - Private (DCP_P) + ADCP_P Power Channel Entity Label @@ -3750,7 +3947,7 @@ boolean developer global - false + true Power Channel State @@ -3795,7 +3992,7 @@ string developer global - Private (MOBILE) + MOBILE Power Channel Entity Label @@ -3804,7 +4001,7 @@ boolean developer global - false + true Power Channel State @@ -3984,7 +4181,7 @@ boolean developer global - false + true Is Main CPU @@ -3998,13 +4195,13 @@ Set CPC to use NAV and Iridium at Boot.
-
+
Entity Label string developer global - GPS + AIS Main entity label @@ -4022,7 +4219,7 @@ integer developer global - 30.0 + 10.0 @@ -4078,39 +4275,9 @@ string developer global - uart:///dev/ttyS10:19200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 10.0 - s - Input timeout - 0.0 - - - Sentence Order - list:string - developer - global - GPGGA, GPROT - - Sentence order - - - Acquisition Frequency - integer - developer - global - 1 + uart:///dev/ttyS10:38400 - Acquisition Frequency - 0 - 5 + Serial port device used to communicate with the sensor Initialization String 0 - Command @@ -4202,89 +4369,1151 @@ - - Initialization String 5 - Command - string + + Sentence Order + list:string developer global - + GPS Sentence order - - Initialization String 5 - Reply - string + + Input Timeout + real developer global - - - + 4.0 + s + Input timeout + 0.0 - - Initialization String 6 - Command - string + + AIS Error - Max + integer developer global - + 3 - + Max erros for Ais messages parser - - Initialization String 6 - Reply - string + + AIS Error - Interval + real + developer + global + 10.0 + + Invertal for checking AIS errors + + + Power Channel + string + developer + global + + + Power Channel + + + Log messages + boolean + developer + global + false + + Add messages received to logs + +
+
+ + Entity Label + string + developer + global + AirMar120WX + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 3.0 + + + + + Deactivation Time + integer + developer + global + 3.0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS8:4800 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 7.0 + s + Input timeout + 0.0 + + + Angle offset + real + developer + global + 5 + ° + Angle offset for relative wind + +
+
+ + Entity Label + string + developer + global + Fluorometers + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + maneuver + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + maneuver + 1 + + True to activate task, false otherwise + + + Serial Port - Device + string + developer + global + /dev/ttyS11 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 19200 + + Serial port Baud Rate + + + Input Timeout + real + developer + global + 5.0 + s + Amount of seconds to wait for data before reporting an error + 2.0 + + + Device Serial Number + string + developer + global + BBFL2W-8379 + + Device's serial number. Required to check communication with device. + + + CDOM -- Dark Counts + integer + developer + global + 62 + + Signal output of the meter in clean water with black tape over detector + + + CDOM -- Scale Factor + real + developer + global + 0.0916 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Chlorophyll -- Dark Counts + integer + developer + global + 49 + + Signal output of the meter in clean water with black tape over detector + + + Chlorophyll -- Scale Factor + real + developer + global + 0.0073 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Turbidity -- Dark Counts + integer + developer + global + 51 + + Signal output of the meter in clean water with black tape over detector + + + Turbidity -- Scale Factor + real + developer + global + 0.0024 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Sampling Duration + real + user + maneuver + 0.0 + + Sampling duration in seconds + + + Sampling Period + real + user + maneuver + 0.0 + + Sampling period in seconds + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. + +
+
+ + Entity Label + string + developer + global + GPS + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 30.0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS9:19200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 10.0 + s + Input timeout + 0.0 + + + Sentence Order + list:string + developer + global + GPGGA, GPROT + + Sentence order + + + Acquisition Frequency + integer + developer + global + 1 + + Acquisition Frequency + 0 + 5 + + + Initialization String 0 - Command + string + developer + global + + + + + + Initialization String 0 - Reply + string + developer + global + + + + + + Initialization String 1 - Command + string + developer + global + + + + + + Initialization String 1 - Reply + string + developer + global + + + + + + Initialization String 2 - Command + string + developer + global + + + + + + Initialization String 2 - Reply + string + developer + global + + + + + + Initialization String 3 - Command + string + developer + global + + + + + + Initialization String 3 - Reply + string + developer + global + + + + + + Initialization String 4 - Command + string + developer + global + + + + + + Initialization String 4 - Reply + string + developer + global + + + + + + Initialization String 5 - Command + string + developer + global + + + + + + Initialization String 5 - Reply + string + developer + global + + + + + + Initialization String 6 - Command + string + developer + global + + + + + + Initialization String 6 - Reply + string + developer + global + + + + + + Initialization String 7 - Command + string + developer + global + + + + + + Initialization String 7 - Reply + string + developer + global + + + + + + Initialization String 8 - Command + string + developer + global + + + + + + Initialization String 8 - Reply + string + developer + global + + + + + + Initialization String 9 - Command + string + developer + global + + + + + + Initialization String 9 - Reply + string + developer + global + + + + +
+
+ + Entity Label + string + developer + global + AHRS + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 20.0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS4 + + IO device URI in the form "uart://DEVICE".This device has only one baud rate. + + + Power Channel - Name + string + developer + global + + + Name of the power channel + + + Hard-Iron Calibration + list:real + developer + global + 0.0410, -0.0470, 0.0 + G + Hard-Iron calibration parameters + 3 + + + Output Frequency + integer + developer + global + 20 + Hz + Output frequency + 1 + 127 + + + Raw Data + boolean + developer + global + false + + Set to true to enable raw data output + + + Rotation Matrix + list:real + developer + global + 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 + + Rotation matrix which is dependent of the mounting position + 9 + + + Timeout - Error + real + developer + global + 3.0 + s + Number of seconds without data before reporting an error + 1.0 + + + Timeout - Failure + real + developer + global + 6.0 + s + Number of seconds without data before restarting task + 1.0 + + + Last Calibration Time + string + user + global + 2024-05-09 14:04 + + Date of last successful calibration + +
+
+ + Entity Label + string + developer + global + ADCP + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 5 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS6:115200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. + + + Sample Time Duration + integer + user + maneuver + 60 + + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + + Periodicity of Data Sampling in seconds. + + + Initialization String 0 - Command + string + developer + global + SETDEFAULT,ALL + + + + + Initialization String 1 - Command + string + developer + global + SETPLAN,MIAVG=1,AVG=1,DIAVG=0,VD=0,MV=10,SA=35,BURST=1,MIBURST=3600,DIBURST=0,SV=0,FN="RAWDATA.ad2cp",SO=0,FREQ=500,NSTT=0\r\n + + + + + Initialization String 2 - Command + string + developer + global + SETAVG,NC=16,CS=4,BD=1.0,CY="ENU",PL=0,AI=1,VP=0.000,VR=5.0,DF=3,NPING=3,NB=4,CH=0,MUX=0,BW="NARROW",ALTI=1,BT=0,ICE=0,ALTISTART=0.5,ALTIEND=70,RAWALTI=60\r\n + + + + + Initialization String 3 - Command + string + developer + global + SETTMAVG,EN=1,CD=1,PD=1,AVG=1,TV=1,TA=1,TC=1,CY="ENU",FO=0,SO=1,DF=3,DISTILT=0,TPG=1,MAPBINS=0\r\n + + + + + Initialization String 4 - Command + string + developer + global + SETTMALTI,EN=1,TS=1,TQ=1,FO=0,SO=1,DF=200,TPR=0\r\n + + + + + Initialization String 5 - Command + string + developer + global + SETTMBURST,EN=0,NS=1,SO=0,FO=0,DF=3,ENAVG=0,CY="ENU",MAPBINS=0\r\n + + + + + Initialization String 6 - Command + string + developer + global + SETINST,BR=115200,RS=232,LED="ON",ORIENT="ZDOWN",CMTOUT=300,DMTOUT=60,CFMTOUT=60\r\n + + + + + Initialization String 7 - Command + string + developer + global + SAVE,ALL\r\n + + + + + Initialization String 8 - Command + string + developer + global + + + + + + Initialization String 9 - Command + string developer global - - Initialization String 7 - Command +
+
+ + Entity Label string developer global - + Dissolved Oxygen + + Main entity label + + + Execution Priority + integer + developer + global + 20 + + Execution priority + + + Activation Time + integer + developer + global + 60 - - Initialization String 7 - Reply - string + + Deactivation Time + integer developer global - + 0 - - Initialization String 8 - Command + + Debug Level string developer global - + None + None, Debug, Trace, Spew + None, Debug, Trace, Spew - - Initialization String 8 - Reply + + Active - Scope string developer global - + global - + Scoped of the 'Active' parameter - - Initialization String 9 - Command + + Active - Visibility string developer global - + developer - + Visibility of the 'Active' parameter - - Initialization String 9 - Reply + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS7:9600 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Measurement String Identifier + string + developer + global + 4835 + + Measurement command string identifier + + + Entity Label - Temperature + string + developer + global + CTD + + Entity label of the CTD + + + Entity Label - Depth + string + developer + global + CTD + + Entity label of the CTD + + + Entity Label - Salinity + string + developer + global + CTD + + Entity label of the CTD + + + Power Channel - Name string developer global @@ -4292,14 +5521,59 @@ + + Data rate + real + developer + global + 1 + Hz + Data Acquisition Rate. + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. + + + Sample Time Duration + integer + user + maneuver + 60 + s + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + s + Periodicity of Data Sampling in seconds. + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + s + Timeout Transmitting Iridium Message. +
-
+
Entity Label string developer global - AHRS + CTD Main entity label @@ -4317,7 +5591,7 @@ integer developer global - 20.0 + 10.0 @@ -4346,7 +5620,7 @@ string developer global - global + maneuver Scoped of the 'Active' parameter @@ -4355,15 +5629,15 @@ string developer global - developer + user Visibility of the 'Active' parameter Active boolean - developer - global + user + maneuver 1 True to activate task, false otherwise @@ -4373,9 +5647,45 @@ string developer global - uart:///dev/ttyS9 + uart:///dev/ttyS5:115200 - IO device URI in the form "uart://DEVICE".This device has only one baud rate. + IO device URI in the form "uart://DEVICE:BAUD" + + + Sample Period (ms) + integer + user + global + 125 + ms + Sample period in milliseconds + + + Sample Time Duration + integer + user + maneuver + 5 + + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 20 + + Periodicity of Data Sampling in seconds. + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. Power Channel - Name @@ -4384,85 +5694,101 @@ global - Name of the power channel + Power channel name for the device. Set to empty to disable. - - Hard-Iron Calibration - list:real + + Input Timeout + real developer global - 0.0, 0.0, 0.0 - G - Hard-Iron calibration parameters - 3 + 60 + + Input timeout in seconds. Must be greater than 2*Sample Time Duration - - Output Frequency +
+
+ + Entity Label + string + developer + global + Thermal Zone + + Main entity label + + + Execution Priority integer developer global - 20 - Hz - Output frequency - 1 - 127 + 10 + + Execution priority - - Raw Data - boolean + + Activation Time + integer developer global - false + 0 - Set to true to enable raw data output + - - Rotation Matrix - list:real + + Deactivation Time + integer developer global - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 + 0 - Rotation matrix which is dependent of the mounting position - 9 + - - Timeout - Error - real + + Debug Level + string developer global - 3.0 - s - Number of seconds without data before reporting an error - 1.0 + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew - - Timeout - Failure + + Execution Frequency real developer global - 6.0 - s - Number of seconds without data before restarting task - 1.0 + 1 + Hz + Frequency at which task is executed + + + Path + string + developer + global + /sys/class/thermal/thermal_zone0/temp + + Path to the sysfs file - - Last Calibration Time + + Entity Label - Temperature string - user + developer global - N/A + Mainboard (Core) - Date of last successful calibration + Entity label of temperature sensor
-
+
Entity Label string developer global - Thermal Zone + Autonaut Supervisor Main entity label @@ -4509,27 +5835,29 @@ real developer global - 1 + 2 Hz Frequency at which task is executed - - Path - string + + Loiter On Service -- Radius + real developer global - /sys/class/thermal/thermal_zone0/temp + 30.0 - Path to the sysfs file + Radius for loiter on service option + 5.0 - - Entity Label - Temperature - string + + Loiter On Service -- Speed + real developer global - Mainboard (Core) + 0.5 - Entity label of temperature sensor + Speed for loiter on service option + 0.1
@@ -5310,6 +6638,145 @@ Maximum amount of seconds to wait for missing fragments in incoming messages
+
+ + Entity Label + string + developer + global + GSM + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 10 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Serial Port - Device + string + developer + global + /dev/ttyUSB3 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 115200 + + Serial port baud rate + + + Reply Timeout + real + developer + global + 2.0 + s + Amount of time to wait for a command reply + + + PIN + string + developer + global + + + PIN Code + + + RSSI Periodicity + real + developer + global + 10 + s + Periodicity of RSSI reports + + + Read SMS Periodicity + real + developer + global + 10 + s + Periodicity of received SMS checks + + + SMS Send Timeout + real + developer + global + 60 + s + Maximum amount of time to wait for SMS send completion + + + USSD code + integer + developer + global + 111 + + USSD code + + + Request Balance + boolean + user + global + false + + Enable Balance Request + + + Balance Periodicity + integer + developer + global + 60 + + Balance Periodicity + +
Entity Label @@ -5498,6 +6965,136 @@ Text messages received via Iridium will be tagged with this origin
+
+ + Entity Label + string + developer + global + Iridium Operation + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + global + 0 + + True to activate task, false otherwise + + + Maximum iridium payload size + integer + developer + global + 250 + + Maximum size of iridium payload messages in bytes. + + + Rate Limiters + list:string + developer + global + PlanControlState:120, EstimatedState:120, VehicleState:120, StateReport:120, FuelLevel:120 + + List of <Message>:<Period> to send messages at a specific period. + + + Filtered Entities + list:string + developer + global + + + List of <Message>:<Entity>+<Entity> that define the source entities allowed to pass message of a specific message type. + + + Transport + list:string + developer + global + PlanControl, PlanControlState, EstimatedState, VehicleState, StateReport, FuelLevel, Aborted + + List of messages to transport + + + Message TTL + integer + developer + global + 120 + + Time to live for iridium messages. + + + Iridium Operation Timeout + integer + developer + global + 600 + + Iridium operation timeout in seconds. + +
Entity Label @@ -5578,7 +7175,7 @@ string developer global - /dev/ttyS8 + /dev/ttyS3 Serial port device used to communicate with the modem @@ -5925,7 +7522,7 @@ list:string developer global - Distance:Altimeter+DVL Filtered+Echo Sounder + Distance:Altimeter+DVL Filtered+Echo Sounder, DevDataText:AIS List of <Message>:<Entity>+<Entity> that define the source entities allowed to pass message of a specific message type. @@ -5961,7 +7558,7 @@ list:string developer global - Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation, AisInfo, RemoteSensorInfo, DevDataText List of messages to transport diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index 01801b2829..af4f31bdf8 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,26 +1,26 @@ - +
- Nome da Entidade + Entity Label string developer global Text Actions - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -29,7 +29,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -38,7 +38,7 @@ - Nível de Depuração + Debug Level string developer global @@ -79,25 +79,25 @@
- Nome da Entidade + Entity Label string developer global Heading Controller - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -106,7 +106,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -115,7 +115,7 @@ - Nível de Depuração + Debug Level string developer global @@ -185,7 +185,7 @@ real developer global - 0.25 + 0.75 Percentage of thrust assistance @@ -461,27 +461,27 @@ Minimum heading error to consider vessel is turning (in degrees).
-
+
- Nome da Entidade + Entity Label string developer global Remote Control - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -490,7 +490,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -499,7 +499,7 @@ - Nível de Depuração + Debug Level string developer global @@ -510,40 +510,40 @@ None, Debug, Trace, Spew - Frequência de Execução + Execution Frequency real developer global 10 Hz - Frequência com que a tarefa é executada + Frequency at which task is executed - Ativa - Escopo + Active - Scope string developer global maneuver - Escopo do parâmetro 'Ativa' + Scoped of the 'Active' parameter - Ativa - Visibilidade + Active - Visibility string developer global developer - Visibilidade do parâmetro 'Ativa' + Visibility of the 'Active' parameter - Ativa + Active boolean developer maneuver true - Verdadeiro para ativar tarefa, falso caso contrário + True to activate task, false otherwise Connection Timeout @@ -563,28 +563,37 @@ + + Entity Label - CAS + string + developer + global + Path Control + + Entity label of CAS entity +
-
+
- Nome da Entidade + Entity Label string developer global Path Control - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -593,7 +602,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -602,7 +611,7 @@ - Nível de Depuração + Debug Level string developer global @@ -855,7 +864,7 @@ string developer global - GPS Navigation + Simulated Navigation Manager Entity label of 'GpsFix' message @@ -873,7 +882,7 @@ string developer global - + AirMar120WX Entity label of 'AbsoluteWind' message @@ -1362,27 +1371,27 @@ 45
-
+
- Nome da Entidade + Entity Label string developer global Communications Relay Maneuver - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -1391,7 +1400,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -1400,7 +1409,7 @@ - Nível de Depuração + Debug Level string developer global @@ -1438,27 +1447,27 @@ Z Mode to use. One of Depth, Altitude or Height.
-
+
- Nome da Entidade + Entity Label string developer global Compass Calibration Maneuver - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -1467,7 +1476,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -1476,7 +1485,7 @@ - Nível de Depuração + Debug Level string developer global @@ -1532,27 +1541,27 @@ Perform compass calibration if true
-
+
- Nome da Entidade + Entity Label string developer global Multiplexer Maneuver - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -1561,7 +1570,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -1570,7 +1579,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2050,27 +2059,76 @@ Minimum radius for StationKeepingExtended to prevent incompatibility with path controller
-
+
- Nome da Entidade + Entity Label string developer global Teleoperation Maneuver - Nome principal da entidade + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + +
+
+ + Entity Label + string + developer + global + CPU Scaling + + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2079,7 +2137,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2088,7 +2146,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2098,28 +2156,55 @@ None, Debug, Trace, Spew None, Debug, Trace, Spew + + Set CPU In Mode + string + developer + global + powersave + + Set CPU In Mode. + + + Use Linux Liquorix + boolean + developer + global + false + + Use Linux Liquorix. + + + Set Maximum CPU Frequency in MHz + integer + developer + global + 500 + + Set Maximum CPU Frequency in MHz. +
- Nome da Entidade + Entity Label string developer global CPU Usage - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2128,7 +2213,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2137,7 +2222,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2148,27 +2233,27 @@ None, Debug, Trace, Spew
-
+
- Nome da Entidade + Entity Label string developer global Clock - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2177,7 +2262,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2186,7 +2271,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2245,27 +2330,27 @@ Change log file after synchronization
-
+
- Nome da Entidade + Entity Label string developer global Emergency Monitor - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2274,7 +2359,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2283,7 +2368,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2294,58 +2379,58 @@ None, Debug, Trace, Spew - Frequência de Execução + Execution Frequency real developer global 1.0 Hz - Frequência com que a tarefa é executada + Frequency at which task is executed - Ativa - Escopo + Active - Scope string developer global idle - Escopo do parâmetro 'Ativa' + Scoped of the 'Active' parameter - Ativa - Visibilidade + Active - Visibility string developer global user - Visibilidade do parâmetro 'Ativa' + Visibility of the 'Active' parameter - Ativa + Active boolean user idle true - Verdadeiro para ativar tarefa, falso caso contrário + True to activate task, false otherwise - Número de Destino de Mensagens SMS + SMS Recipient Number string user global +351912439480 - Número de telefone do destinatário de mensagens SMS + Phone number of the SMS recipient - Timeout de Perda de Comunicações + Lost Communications Timeout real user global 1800 s - Timeout de Perda de Comunicações + Lost Communications Timeout 60.0 @@ -2353,7 +2438,7 @@ string developer global - Iridium + Both Desired transmission interface GSM, Iridium, Both @@ -2380,27 +2465,27 @@ 0.0
-
+
- Nome da Entidade + Entity Label string developer global Entity Monitor - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2409,7 +2494,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2418,7 +2503,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2443,7 +2528,7 @@ list:string developer global - Daemon, GPS, Navigation, Operational Limits, Path Control + Daemon, GPS, Operational Limits, Path Control Default entities to monitor @@ -2452,7 +2537,7 @@ list:string developer global - Clock, Collisions + Clock, Navigation Manager Additional default entities to monitor in Hardware profile @@ -2478,25 +2563,25 @@
- Nome da Entidade + Entity Label string developer global Log Monitor - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2505,7 +2590,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2514,7 +2599,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2534,27 +2619,27 @@ Log time in format %ud:%uh:%um
-
+
- Nome da Entidade + Entity Label string developer global Operational Limits - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2563,7 +2648,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2572,7 +2657,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2583,13 +2668,13 @@ None, Debug, Trace, Spew - Frequência de Execução + Execution Frequency real developer global 4 Hz - Frequência com que a tarefa é executada + Frequency at which task is executed Initial Setting - Maximum Depth @@ -2674,27 +2759,139 @@ 0.0
+
+ + Entity Label + string + developer + global + Payload Monitor + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + maneuver + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + maneuver + 1 + + True to activate task, false otherwise + + + Payload timeout + real + developer + global + 120 + + Payload timeout in seconds. + + + Payload Messages + list:string + developer + global + EstimatedState:Navigation Manager, Temperature:CTD, Temperature:AirMar120WX, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager + + List of messages <Message>:<Entity> to send using Iridium. + + + Maximum payload size + integer + developer + global + 250 + + Maximum size of iridium payload messages in bytes. + + + Message TTL + integer + developer + global + 120 + + Time to live for iridium messages. + +
- Nome da Entidade + Entity Label string developer global Wave Frequency Estimator - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2703,7 +2900,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2712,7 +2909,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2723,7 +2920,7 @@ None, Debug, Trace, Spew - Ativa + Active boolean developer global @@ -2845,25 +3042,25 @@
- Nome da Entidade + Entity Label string developer global Navigation Manager - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2872,7 +3069,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -2881,7 +3078,7 @@ - Nível de Depuração + Debug Level string developer global @@ -2916,7 +3113,7 @@ global GPS - Name of preferred navigation unit. + Name of preferred GPS navigation unit. Secondary unit @@ -2925,7 +3122,7 @@ global CPC - Name of secondary preferred navigation unit. + Name of secondary preferred GPS navigation unit. Third unit @@ -2934,7 +3131,7 @@ global AIS - Name of third preferred navigation unit. + Name of third preferred GPS navigation unit. Convert Height to Geoid Height @@ -2965,27 +3162,27 @@ Distance needed for reference change.
-
+
- Nome da Entidade + Entity Label string developer global Plan Database - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -2994,7 +3191,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -3003,7 +3200,7 @@ - Nível de Depuração + Debug Level string developer global @@ -3023,27 +3220,27 @@ Path to DB file
-
+
- Nome da Entidade + Entity Label string developer global Plan Engine - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -3052,7 +3249,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -3061,7 +3258,7 @@ - Nível de Depuração + Debug Level string developer global @@ -3171,27 +3368,27 @@ Entity label of the Plan Generator
-
+
- Nome da Entidade + Entity Label string developer global Plan Generator - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -3200,7 +3397,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -3209,7 +3406,7 @@ - Nível de Depuração + Debug Level string developer global @@ -3276,25 +3473,25 @@
- Nome da Entidade + Entity Label string developer global CPC - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -3303,7 +3500,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -3312,7 +3509,7 @@ - Nível de Depuração + Debug Level string developer global @@ -3323,38 +3520,38 @@ None, Debug, Trace, Spew - Ativa - Escopo + Active - Scope string developer global global - Escopo do parâmetro 'Ativa' + Scoped of the 'Active' parameter - Ativa - Visibilidade + Active - Visibility string developer global developer - Visibilidade do parâmetro 'Ativa' + Visibility of the 'Active' parameter - Ativa + Active boolean developer global 1 - Verdadeiro para ativar tarefa, falso caso contrário + True to activate task, false otherwise IO Port - Device string developer global - uart:///dev/ttyCPC:115200 + uart:///dev/ttyS2:115200 IO device URI in the form "uart://DEVICE:BAUD" @@ -3570,7 +3767,7 @@ boolean developer global - false + true Power Channel State @@ -3588,7 +3785,7 @@ boolean developer global - false + true Power Channel State @@ -3651,7 +3848,7 @@ string developer global - Private (ECHOTRIP) + ECHOTRIP Power Channel Entity Label @@ -3660,7 +3857,7 @@ boolean developer global - false + true Power Channel State @@ -3669,7 +3866,7 @@ string developer global - Private (OXYGEN) + OXYGEN Power Channel Entity Label @@ -3678,7 +3875,7 @@ boolean developer global - false + true Power Channel State @@ -3687,7 +3884,7 @@ string developer global - Private (AIRMAR) + AIRMAR Power Channel Entity Label @@ -3696,7 +3893,7 @@ boolean developer global - false + true Power Channel State @@ -3705,7 +3902,7 @@ string developer global - Private (CTD_P) + CTD_P Power Channel Entity Label @@ -3714,7 +3911,7 @@ boolean developer global - false + true Power Channel State @@ -3741,7 +3938,7 @@ string developer global - Private (DCP_P) + ADCP_P Power Channel Entity Label @@ -3750,7 +3947,7 @@ boolean developer global - false + true Power Channel State @@ -3795,7 +3992,7 @@ string developer global - Private (MOBILE) + MOBILE Power Channel Entity Label @@ -3804,7 +4001,7 @@ boolean developer global - false + true Power Channel State @@ -3984,7 +4181,7 @@ boolean developer global - false + true Is Main CPU @@ -3998,36 +4195,36 @@ Set CPC to use NAV and Iridium at Boot.
-
+
- Nome da Entidade + Entity Label string developer global - GPS + AIS - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global - 30.0 + 10.0 - Tempo de Desativação + Deactivation Time integer developer global @@ -4036,7 +4233,7 @@ - Nível de Depuração + Debug Level string developer global @@ -4047,70 +4244,40 @@ None, Debug, Trace, Spew - Ativa - Escopo + Active - Scope string developer global global - Escopo do parâmetro 'Ativa' + Scoped of the 'Active' parameter - Ativa - Visibilidade + Active - Visibility string developer global developer - Visibilidade do parâmetro 'Ativa' + Visibility of the 'Active' parameter - Ativa + Active boolean developer global 1 - Verdadeiro para ativar tarefa, falso caso contrário + True to activate task, false otherwise IO Port - Device string developer global - uart:///dev/ttyS10:19200 - - IO device URI in the form "uart://DEVICE:BAUD" - - - Input Timeout - real - developer - global - 10.0 - s - Input timeout - 0.0 - - - Sentence Order - list:string - developer - global - GPGGA, GPROT - - Sentence order - - - Acquisition Frequency - integer - developer - global - 1 + uart:///dev/ttyS10:38400 - Acquisition Frequency - 0 - 5 + Serial port device used to communicate with the sensor Initialization String 0 - Command @@ -4202,80 +4369,1012 @@ - - Initialization String 5 - Command - string + + Sentence Order + list:string developer global - + GPS Sentence order - - Initialization String 5 - Reply - string + + Input Timeout + real developer global - - - + 4.0 + s + Input timeout + 0.0 - - Initialization String 6 - Command - string + + AIS Error - Max + integer developer global - + 3 - + Max erros for Ais messages parser - - Initialization String 6 - Reply - string + + AIS Error - Interval + real developer global - + 10.0 - + Invertal for checking AIS errors - - Initialization String 7 - Command + + Power Channel string developer global - + Power Channel - - Initialization String 7 - Reply - string + + Log messages + boolean developer global - + false - + Add messages received to logs - - Initialization String 8 - Command +
+
+ + Entity Label string developer global - + AirMar120WX - + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 3.0 + + + + + Deactivation Time + integer + developer + global + 3.0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS8:4800 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 7.0 + s + Input timeout + 0.0 + + + Angle offset + real + developer + global + 5 + ° + Angle offset for relative wind + +
+
+ + Entity Label + string + developer + global + Fluorometers + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + maneuver + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + maneuver + 1 + + True to activate task, false otherwise + + + Serial Port - Device + string + developer + global + /dev/ttyS11 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 19200 + + Serial port Baud Rate + + + Input Timeout + real + developer + global + 5.0 + s + Amount of seconds to wait for data before reporting an error + 2.0 + + + Device Serial Number + string + developer + global + BBFL2W-8379 + + Device's serial number. Required to check communication with device. + + + CDOM -- Dark Counts + integer + developer + global + 62 + + Signal output of the meter in clean water with black tape over detector + + + CDOM -- Scale Factor + real + developer + global + 0.0916 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Chlorophyll -- Dark Counts + integer + developer + global + 49 + + Signal output of the meter in clean water with black tape over detector + + + Chlorophyll -- Scale Factor + real + developer + global + 0.0073 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Turbidity -- Dark Counts + integer + developer + global + 51 + + Signal output of the meter in clean water with black tape over detector + + + Turbidity -- Scale Factor + real + developer + global + 0.0024 + + Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer + + + Sampling Duration + real + user + maneuver + 0.0 + + Sampling duration in seconds + + + Sampling Period + real + user + maneuver + 0.0 + + Sampling period in seconds + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. + +
+
+ + Entity Label + string + developer + global + GPS + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 30.0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS9:19200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Input Timeout + real + developer + global + 10.0 + s + Input timeout + 0.0 + + + Sentence Order + list:string + developer + global + GPGGA, GPROT + + Sentence order + + + Acquisition Frequency + integer + developer + global + 1 + + Acquisition Frequency + 0 + 5 + + + Initialization String 0 - Command + string + developer + global + + + + + + Initialization String 0 - Reply + string + developer + global + + + + + + Initialization String 1 - Command + string + developer + global + + + + + + Initialization String 1 - Reply + string + developer + global + + + + + + Initialization String 2 - Command + string + developer + global + + + + + + Initialization String 2 - Reply + string + developer + global + + + + + + Initialization String 3 - Command + string + developer + global + + + + + + Initialization String 3 - Reply + string + developer + global + + + + + + Initialization String 4 - Command + string + developer + global + + + + + + Initialization String 4 - Reply + string + developer + global + + + + + + Initialization String 5 - Command + string + developer + global + + + + + + Initialization String 5 - Reply + string + developer + global + + + + + + Initialization String 6 - Command + string + developer + global + + + + + + Initialization String 6 - Reply + string + developer + global + + + + + + Initialization String 7 - Command + string + developer + global + + + + + + Initialization String 7 - Reply + string + developer + global + + + + + + Initialization String 8 - Command + string + developer + global + + + Initialization String 8 - Reply string developer global - + + + + + + Initialization String 9 - Command + string + developer + global + + + + + + Initialization String 9 - Reply + string + developer + global + + + + +
+
+ + Entity Label + string + developer + global + AHRS + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 20.0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS4 + + IO device URI in the form "uart://DEVICE".This device has only one baud rate. + + + Power Channel - Name + string + developer + global + + + Name of the power channel + + + Hard-Iron Calibration + list:real + developer + global + 0.0410, -0.0470, 0.0 + G + Hard-Iron calibration parameters + 3 + + + Output Frequency + integer + developer + global + 20 + Hz + Output frequency + 1 + 127 + + + Raw Data + boolean + developer + global + false + + Set to true to enable raw data output + + + Rotation Matrix + list:real + developer + global + 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 + + Rotation matrix which is dependent of the mounting position + 9 + + + Timeout - Error + real + developer + global + 3.0 + s + Number of seconds without data before reporting an error + 1.0 + + + Timeout - Failure + real + developer + global + 6.0 + s + Number of seconds without data before restarting task + 1.0 + + + Last Calibration Time + string + user + global + 2024-05-09 14:04 + + Date of last successful calibration + +
+
+ + Entity Label + string + developer + global + ADCP + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 5 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + developer + + Visibility of the 'Active' parameter + + + Active + boolean + developer + global + 1 + + True to activate task, false otherwise + + + IO Port - Device + string + developer + global + uart:///dev/ttyS6:115200 + + IO device URI in the form "uart://DEVICE:BAUD" + + + Timeout Transmitting Iridium Message + integer + developer + global + 60 + + Timeout Transmitting Iridium Message. + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. + + + Sample Time Duration + integer + user + maneuver + 60 + + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + + Periodicity of Data Sampling in seconds. + + + Initialization String 0 - Command + string + developer + global + SETDEFAULT,ALL + + + + + Initialization String 1 - Command + string + developer + global + SETPLAN,MIAVG=1,AVG=1,DIAVG=0,VD=0,MV=10,SA=35,BURST=1,MIBURST=3600,DIBURST=0,SV=0,FN="RAWDATA.ad2cp",SO=0,FREQ=500,NSTT=0\r\n + + + + + Initialization String 2 - Command + string + developer + global + SETAVG,NC=16,CS=4,BD=1.0,CY="ENU",PL=0,AI=1,VP=0.000,VR=5.0,DF=3,NPING=3,NB=4,CH=0,MUX=0,BW="NARROW",ALTI=1,BT=0,ICE=0,ALTISTART=0.5,ALTIEND=70,RAWALTI=60\r\n + + + + + Initialization String 3 - Command + string + developer + global + SETTMAVG,EN=1,CD=1,PD=1,AVG=1,TV=1,TA=1,TC=1,CY="ENU",FO=0,SO=1,DF=3,DISTILT=0,TPG=1,MAPBINS=0\r\n - - Initialization String 9 - Command + + Initialization String 4 - Command + string + developer + global + SETTMALTI,EN=1,TS=1,TQ=1,FO=0,SO=1,DF=200,TPR=0\r\n + + + + + Initialization String 5 - Command + string + developer + global + SETTMBURST,EN=0,NS=1,SO=0,FO=0,DF=3,ENAVG=0,CY="ENU",MAPBINS=0\r\n + + + + + Initialization String 6 - Command + string + developer + global + SETINST,BR=115200,RS=232,LED="ON",ORIENT="ZDOWN",CMTOUT=300,DMTOUT=60,CFMTOUT=60\r\n + + + + + Initialization String 7 - Command + string + developer + global + SAVE,ALL\r\n + + + + + Initialization String 8 - Command string developer global @@ -4283,8 +5382,8 @@ - - Initialization String 9 - Reply + + Initialization String 9 - Command string developer global @@ -4293,36 +5392,36 @@
-
+
- Nome da Entidade + Entity Label string developer global - AHRS + Dissolved Oxygen - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global - 10 + 20 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global - 20.0 + 60 - Tempo de Desativação + Deactivation Time integer developer global @@ -4331,7 +5430,7 @@ - Nível de Depuração + Debug Level string developer global @@ -4342,40 +5441,76 @@ None, Debug, Trace, Spew - Ativa - Escopo + Active - Scope string developer global global - Escopo do parâmetro 'Ativa' + Scoped of the 'Active' parameter - Ativa - Visibilidade + Active - Visibility string developer global developer - Visibilidade do parâmetro 'Ativa' + Visibility of the 'Active' parameter - Ativa + Active boolean developer global 1 - Verdadeiro para ativar tarefa, falso caso contrário + True to activate task, false otherwise IO Port - Device string developer global - uart:///dev/ttyS9 + uart:///dev/ttyS7:9600 - IO device URI in the form "uart://DEVICE".This device has only one baud rate. + IO device URI in the form "uart://DEVICE:BAUD" + + + Measurement String Identifier + string + developer + global + 4835 + + Measurement command string identifier + + + Entity Label - Temperature + string + developer + global + CTD + + Entity label of the CTD + + + Entity Label - Depth + string + developer + global + CTD + + Entity label of the CTD + + + Entity Label - Salinity + string + developer + global + CTD + + Entity label of the CTD Power Channel - Name @@ -4384,99 +5519,290 @@ global - Name of the power channel + - - Hard-Iron Calibration - list:real + + Data rate + real developer global - 0.0, 0.0, 0.0 - G - Hard-Iron calibration parameters - 3 + 1 + Hz + Data Acquisition Rate. - - Output Frequency + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. + + + Sample Time Duration + integer + user + maneuver + 60 + s + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + s + Periodicity of Data Sampling in seconds. + + + Timeout Transmitting Iridium Message integer developer global - 20 - Hz - Output frequency - 1 - 127 + 60 + s + Timeout Transmitting Iridium Message. - - Raw Data +
+
+ + Entity Label + string + developer + global + CTD + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 10.0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + maneuver + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active boolean + user + maneuver + 1 + + True to activate task, false otherwise + + + IO Port - Device + string developer global - false + uart:///dev/ttyS5:115200 - Set to true to enable raw data output + IO device URI in the form "uart://DEVICE:BAUD" - - Rotation Matrix - list:real + + Sample Period (ms) + integer + user + global + 125 + ms + Sample period in milliseconds + + + Sample Time Duration + integer + user + maneuver + 5 + + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 20 + + Periodicity of Data Sampling in seconds. + + + Timeout Transmitting Iridium Message + integer developer global - 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 + 60 - Rotation matrix which is dependent of the mounting position - 9 + Timeout Transmitting Iridium Message. + + + Power Channel - Name + string + developer + global + + + Power channel name for the device. Set to empty to disable. + + + Input Timeout + real + developer + global + 60 + + Input timeout in seconds. Must be greater than 2*Sample Time Duration + +
+
+ + Entity Label + string + developer + global + Thermal Zone + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew - - Timeout - Error + + Execution Frequency real developer global - 3.0 - s - Number of seconds without data before reporting an error - 1.0 + 1 + Hz + Frequency at which task is executed - - Timeout - Failure - real + + Path + string developer global - 6.0 - s - Number of seconds without data before restarting task - 1.0 + /sys/class/thermal/thermal_zone0/temp + + Path to the sysfs file - - Last Calibration Time + + Entity Label - Temperature string - user + developer global - N/A + Mainboard (Core) - Date of last successful calibration + Entity label of temperature sensor
-
+
- Nome da Entidade + Entity Label string developer global - Thermal Zone + Autonaut Supervisor - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -4485,7 +5811,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -4494,7 +5820,7 @@ - Nível de Depuração + Debug Level string developer global @@ -4505,54 +5831,56 @@ None, Debug, Trace, Spew - Frequência de Execução + Execution Frequency real developer global - 1 + 2 Hz - Frequência com que a tarefa é executada + Frequency at which task is executed - - Path - string + + Loiter On Service -- Radius + real developer global - /sys/class/thermal/thermal_zone0/temp + 30.0 - Path to the sysfs file + Radius for loiter on service option + 5.0 - - Entity Label - Temperature - string + + Loiter On Service -- Speed + real developer global - Mainboard (Core) + 0.5 - Entity label of temperature sensor + Speed for loiter on service option + 0.1
-
+
- Nome da Entidade + Entity Label string developer global Power Supervisor - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -4561,7 +5889,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -4570,7 +5898,7 @@ - Nível de Depuração + Debug Level string developer global @@ -4617,27 +5945,27 @@ Name of the slave systems
-
+
- Nome da Entidade + Entity Label string developer global Report Supervisor - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -4646,7 +5974,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -4655,7 +5983,7 @@ - Nível de Depuração + Debug Level string developer global @@ -4666,7 +5994,7 @@ None, Debug, Trace, Spew - Relatórios Acústicos + Acoustic Reports boolean user global @@ -4675,7 +6003,7 @@ Enable acoustic system state reporting - Periodicidade de Relatórios Acústicos + Acoustic Reports Periodicity real user global @@ -4686,7 +6014,7 @@ 600 - Relatórios de Rádio + Radio Reports boolean user global @@ -4695,7 +6023,7 @@ Enable Radio system state reporting - Periodicidade de relatórios de rádio + Radio Reports Periodicity real user global @@ -4706,27 +6034,27 @@ 600
-
+
- Nome da Entidade + Entity Label string developer global Vehicle Supervisor - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -4735,7 +6063,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -4744,7 +6072,7 @@ - Nível de Depuração + Debug Level string developer global @@ -4755,13 +6083,13 @@ None, Debug, Trace, Spew - Frequência de Execução + Execution Frequency real developer global 2 Hz - Frequência com que a tarefa é executada + Frequency at which task is executed Vital Entities @@ -4791,27 +6119,27 @@ Timeout for starting or stopping a maneuver
-
+
- Nome da Entidade + Entity Label string developer global Service Announcer - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -4820,7 +6148,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -4829,7 +6157,7 @@ - Nível de Depuração + Debug Level string developer global @@ -4930,27 +6258,27 @@ List of interfaces whose services will not be announced
-
+
- Nome da Entidade + Entity Label string developer global Cache - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -4959,7 +6287,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -4968,7 +6296,7 @@ - Nível de Depuração + Debug Level string developer global @@ -4988,27 +6316,27 @@ List of messages ordered by loading order
-
+
- Nome da Entidade + Entity Label string developer global Communications Manager - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5017,7 +6345,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5026,7 +6354,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5100,27 +6428,27 @@ Send Iridium text messages as plain text (and not IMC)
-
+
- Nome da Entidade + Entity Label string developer global Service Discovery - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5129,7 +6457,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5138,7 +6466,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5176,27 +6504,27 @@ Print incoming messages (Debug)
-
+
- Nome da Entidade + Entity Label string developer global FTP Server - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5205,7 +6533,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5214,7 +6542,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5252,27 +6580,27 @@ Timeout period of a session
-
+
- Nome da Entidade + Entity Label string developer global Message Fragments - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5281,7 +6609,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5290,7 +6618,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5310,27 +6638,166 @@ Maximum amount of seconds to wait for missing fragments in incoming messages
-
+
+ + Entity Label + string + developer + global + GSM + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 10 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Serial Port - Device + string + developer + global + /dev/ttyUSB3 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 115200 + + Serial port baud rate + + + Reply Timeout + real + developer + global + 2.0 + s + Amount of time to wait for a command reply + + + PIN + string + developer + global + + + PIN Code + + + RSSI Periodicity + real + developer + global + 10 + s + Periodicity of RSSI reports + + + Read SMS Periodicity + real + developer + global + 10 + s + Periodicity of received SMS checks + + + SMS Send Timeout + real + developer + global + 60 + s + Maximum amount of time to wait for SMS send completion + + + USSD code + integer + developer + global + 111 + + USSD code + + + Request Balance + boolean + user + global + false + + Enable Balance Request + + + Balance Periodicity + integer + developer + global + 60 + + Balance Periodicity + +
+
- Nome da Entidade + Entity Label string developer global HTTP Server - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5339,7 +6806,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5348,7 +6815,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5386,27 +6853,27 @@ List of messages to transport
-
+
- Nome da Entidade + Entity Label string developer global Iridium Transport - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5415,7 +6882,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5424,7 +6891,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5435,31 +6902,31 @@ None, Debug, Trace, Spew - Ativa - Escopo + Active - Scope string developer global global - Escopo do parâmetro 'Ativa' + Scoped of the 'Active' parameter - Ativa - Visibilidade + Active - Visibility string developer global user - Visibilidade do parâmetro 'Ativa' + Visibility of the 'Active' parameter - Ativa + Active boolean user global true - Verdadeiro para ativar tarefa, falso caso contrário + True to activate task, false otherwise Device updates - Periodicity @@ -5498,27 +6965,157 @@ Text messages received via Iridium will be tagged with this origin
-
+
+ + Entity Label + string + developer + global + Iridium Operation + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Active - Scope + string + developer + global + global + + Scoped of the 'Active' parameter + + + Active - Visibility + string + developer + global + user + + Visibility of the 'Active' parameter + + + Active + boolean + user + global + 0 + + True to activate task, false otherwise + + + Maximum iridium payload size + integer + developer + global + 250 + + Maximum size of iridium payload messages in bytes. + + + Rate Limiters + list:string + developer + global + PlanControlState:120, EstimatedState:120, VehicleState:120, StateReport:120, FuelLevel:120 + + List of <Message>:<Period> to send messages at a specific period. + + + Filtered Entities + list:string + developer + global + + + List of <Message>:<Entity>+<Entity> that define the source entities allowed to pass message of a specific message type. + + + Transport + list:string + developer + global + PlanControl, PlanControlState, EstimatedState, VehicleState, StateReport, FuelLevel, Aborted + + List of messages to transport + + + Message TTL + integer + developer + global + 120 + + Time to live for iridium messages. + + + Iridium Operation Timeout + integer + developer + global + 600 + + Iridium operation timeout in seconds. + +
+
- Nome da Entidade + Entity Label string developer global Iridium Modem - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5527,7 +7124,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5536,7 +7133,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5547,38 +7144,38 @@ None, Debug, Trace, Spew - Ativa - Escopo + Active - Scope string developer global global - Escopo do parâmetro 'Ativa' + Scoped of the 'Active' parameter - Ativa - Visibilidade + Active - Visibility string developer global user - Visibilidade do parâmetro 'Ativa' + Visibility of the 'Active' parameter - Ativa + Active boolean user global true - Verdadeiro para ativar tarefa, falso caso contrário + True to activate task, false otherwise Serial Port - Device string developer global - /dev/ttyS8 + /dev/ttyS3 Serial port device used to communicate with the modem @@ -5666,27 +7263,27 @@ 5
-
+
- Nome da Entidade + Entity Label string developer global Log Book - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5695,7 +7292,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5704,7 +7301,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5715,27 +7312,27 @@ None, Debug, Trace, Spew
-
+
- Nome da Entidade + Entity Label string developer global Logger - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 2 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5744,7 +7341,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5753,7 +7350,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5811,25 +7408,25 @@
- Nome da Entidade + Entity Label string developer global UDP - Nome principal da entidade + Main entity label - Prioridade de Execução + Execution Priority integer developer global 10 - Prioridade de execução + Execution priority - Tempo de Ativação + Activation Time integer developer global @@ -5838,7 +7435,7 @@ - Tempo de Desativação + Deactivation Time integer developer global @@ -5847,7 +7444,7 @@ - Nível de Depuração + Debug Level string developer global @@ -5925,7 +7522,7 @@ list:string developer global - Distance:Altimeter+DVL Filtered+Echo Sounder + Distance:Altimeter+DVL Filtered+Echo Sounder, DevDataText:AIS List of <Message>:<Entity>+<Entity> that define the source entities allowed to pass message of a specific message type. @@ -5961,7 +7558,7 @@ list:string developer global - Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation + Acceleration, AngularVelocity, Current, CpuUsage, DevCalibrationControl, DevCalibrationState, DesiredHeading, DesiredHeadingRate, DesiredSpeed, Distance, EntityList, EntityParameters, EntityState, EstimatedState, EulerAngles, FollowRefState, FuelLevel, GpsFix, Heartbeat, IridiumMsgRx, IridiumMsgTx, IridiumTxStatus, LogBookEntry, LogBookControl, ManeuverDone, OperationalLimits, PathControlState, PlanControl, PlanControlState, PlanDB, PlanGeneration, PlanSpecification, PowerChannelState, ReportControl, RemoteActions, RemoteActionsRequest, RSSI, SimulatedState, SmsRequest, SmsStatus, StateReport, StorageUsage, TCPRequest, TCPStatus, Temperature, Teleoperation, TeleoperationDone, TextMessage, TransmissionRequest, TransmissionStatus, TrexObservation, TrexOperation, TrexToken, TrexPlan, UamTxFrame, UamRxFrame, UamTxStatus, UamRxRange, VehicleMedium, VehicleState, Voltage, AbsoluteWind, AisInfo, ArmingState, CurrentProfile, Displacement, ENCAwareness, Frequency, MagneticField, Rpm, ServoPosition, SetServoPosition, SetThrusterActuation, AisInfo, RemoteSensorInfo, DevDataText List of messages to transport From 8a5c1bfce7a5a396960923844714c2f9ab4ba70d Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 1 Aug 2024 18:49:02 +0100 Subject: [PATCH 40/92] comm/iridium/IridiumManager: Cleanup. --- src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java index 02c5b534aa..a091a9e822 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java @@ -33,6 +33,7 @@ package pt.lsts.neptus.comm.iridium; import java.awt.Component; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -104,7 +105,7 @@ public IridiumMessenger getCurrentMessenger() { private Runnable pollMessages = new Runnable() { - Date lastTime = new Date(System.currentTimeMillis() - 3600 * 1000); + Date lastTime = new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); @Override public void run() { try { From 20522ddd1b44c6e9531a6311e0511c0cb88bd572 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 1 Aug 2024 18:51:49 +0100 Subject: [PATCH 41/92] comm/manager/imc/ImcMsgManager: Don't change the src entity for not own messages. --- src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java index fc27bcd7c6..1d611698f0 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java @@ -1475,7 +1475,8 @@ public int registerEntity(String name) throws InvalidNameException { * @param message */ private void checkAndSetMessageSrcEntity(IMCMessage message) { - if (message.getSrcEnt() == 0 || message.getSrcEnt() == IMCMessage.DEFAULT_ENTITY_ID) { + if (ImcMsgManager.getManager().getLocalId().intValue() == message.getSrc() && + (message.getSrcEnt() == 0 || message.getSrcEnt() == IMCMessage.DEFAULT_ENTITY_ID)) { String caller = getCallerClass(); if (caller != null) { From 5da0583b086e9ddc83ee72ef45d7c81b1505240b Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 1 Aug 2024 18:52:45 +0100 Subject: [PATCH 42/92] plugins/sunfish/iridium/feedback/IridiumStatusTableModel: Updated for new ImcFullIridiumMessage. --- .../sunfish/iridium/feedback/IridiumStatusTableModel.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatusTableModel.java b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatusTableModel.java index 0b5778c537..714c1e3941 100644 --- a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatusTableModel.java +++ b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatusTableModel.java @@ -220,7 +220,8 @@ public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { case TIMESTAMP: { - if(messageType.equalsIgnoreCase("ImcIridiumMessage")) { + if(messageType.equalsIgnoreCase("ImcIridiumMessage") || + messageType.equalsIgnoreCase("ImcFullIridiumMessage")) { IMCMessage msg = ((ImcIridiumMessage) m).getMsg(); if(msg.getMgid() == StateReport.ID_STATIC) { long stime = ((StateReport) msg).getStime() * 1000; @@ -255,7 +256,8 @@ else if (dst == 65535 || dst == ImcMsgManager.getManager().getLocalId().intValue } return IridiumCommsStatus.UNCERTAIN; case MSG_TYPE: - if(messageType.equalsIgnoreCase("ImcIridiumMessage")) + if(messageType.equalsIgnoreCase("ImcIridiumMessage") || + messageType.equalsIgnoreCase("ImcFullIridiumMessage")) return ((ImcIridiumMessage) m).getMsg().getClass().getSimpleName(); else return messageType; From 7a7a1fb540b9fb8f3a8767c3d28c3492f1da1b4f Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 2 Aug 2024 18:40:32 +0100 Subject: [PATCH 43/92] conf/params/caravel: Updated parameters. --- conf/params/caravel.en_US.xml | 8 +- conf/params/caravel.pt_PT.xml | 972 +++++++++++++++++----------------- 2 files changed, 490 insertions(+), 490 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 4bef2d036e..5ea35e5303 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -909,7 +909,7 @@ boolean developer global - true + false Enable collision avoidance algorithm @@ -918,7 +918,7 @@ boolean developer global - true + false Enable anti-grounding algorithm @@ -2848,7 +2848,7 @@ list:string developer global - EstimatedState:Navigation Manager, Temperature:CTD, Temperature:AirMar120WX, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager + EstimatedState:Navigation Manager, Temperature:CTD, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager List of messages <Message>:<Entity> to send using Iridium. diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index af4f31bdf8..aa0917178b 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,26 +1,26 @@ - +
- Entity Label + Nome da Entidade string developer global Text Actions - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -29,7 +29,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -38,7 +38,7 @@ - Debug Level + Nível de Depuração string developer global @@ -79,25 +79,25 @@
- Entity Label + Nome da Entidade string developer global Heading Controller - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -106,7 +106,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -115,7 +115,7 @@ - Debug Level + Nível de Depuração string developer global @@ -461,27 +461,27 @@ Minimum heading error to consider vessel is turning (in degrees).
-
+
- Entity Label + Nome da Entidade string developer global Remote Control - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -490,7 +490,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -499,7 +499,7 @@ - Debug Level + Nível de Depuração string developer global @@ -510,40 +510,40 @@ None, Debug, Trace, Spew - Execution Frequency + Frequência de Execução real developer global 10 Hz - Frequency at which task is executed + Frequência com que a tarefa é executada - Active - Scope + Ativa - Escopo string developer global maneuver - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global developer - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean developer maneuver true - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário Connection Timeout @@ -573,27 +573,27 @@ Entity label of CAS entity
-
+
- Entity Label + Nome da Entidade string developer global Path Control - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -602,7 +602,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -611,7 +611,7 @@ - Debug Level + Nível de Depuração string developer global @@ -909,7 +909,7 @@ boolean developer global - true + false Enable collision avoidance algorithm @@ -918,7 +918,7 @@ boolean developer global - true + false Enable anti-grounding algorithm @@ -1371,27 +1371,27 @@ 45
-
+
- Entity Label + Nome da Entidade string developer global Communications Relay Maneuver - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -1400,7 +1400,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -1409,7 +1409,7 @@ - Debug Level + Nível de Depuração string developer global @@ -1447,27 +1447,27 @@ Z Mode to use. One of Depth, Altitude or Height.
-
+
- Entity Label + Nome da Entidade string developer global Compass Calibration Maneuver - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -1476,7 +1476,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -1485,7 +1485,7 @@ - Debug Level + Nível de Depuração string developer global @@ -1541,27 +1541,27 @@ Perform compass calibration if true
-
+
- Entity Label + Nome da Entidade string developer global Multiplexer Maneuver - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -1570,7 +1570,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -1579,7 +1579,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2059,27 +2059,27 @@ Minimum radius for StationKeepingExtended to prevent incompatibility with path controller
-
+
- Entity Label + Nome da Entidade string developer global Teleoperation Maneuver - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2088,7 +2088,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2097,7 +2097,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2110,25 +2110,25 @@
- Entity Label + Nome da Entidade string developer global CPU Scaling - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2137,7 +2137,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2146,7 +2146,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2186,25 +2186,25 @@
- Entity Label + Nome da Entidade string developer global CPU Usage - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2213,7 +2213,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2222,7 +2222,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2233,27 +2233,27 @@ None, Debug, Trace, Spew
-
+
- Entity Label + Nome da Entidade string developer global Clock - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2262,7 +2262,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2271,7 +2271,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2330,27 +2330,27 @@ Change log file after synchronization
-
+
- Entity Label + Nome da Entidade string developer global Emergency Monitor - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2359,7 +2359,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2368,7 +2368,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2379,58 +2379,58 @@ None, Debug, Trace, Spew - Execution Frequency + Frequência de Execução real developer global 1.0 Hz - Frequency at which task is executed + Frequência com que a tarefa é executada - Active - Scope + Ativa - Escopo string developer global idle - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global user - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean user idle true - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário - SMS Recipient Number + Número de Destino de Mensagens SMS string user global +351912439480 - Phone number of the SMS recipient + Número de telefone do destinatário de mensagens SMS - Lost Communications Timeout + Timeout de Perda de Comunicações real user global 1800 s - Lost Communications Timeout + Timeout de Perda de Comunicações 60.0 @@ -2465,27 +2465,27 @@ 0.0
-
+
- Entity Label + Nome da Entidade string developer global Entity Monitor - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2494,7 +2494,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2503,7 +2503,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2563,25 +2563,25 @@
- Entity Label + Nome da Entidade string developer global Log Monitor - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2590,7 +2590,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2599,7 +2599,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2619,27 +2619,27 @@ Log time in format %ud:%uh:%um
-
+
- Entity Label + Nome da Entidade string developer global Operational Limits - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2648,7 +2648,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2657,7 +2657,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2668,13 +2668,13 @@ None, Debug, Trace, Spew - Execution Frequency + Frequência de Execução real developer global 4 Hz - Frequency at which task is executed + Frequência com que a tarefa é executada Initial Setting - Maximum Depth @@ -2761,25 +2761,25 @@
- Entity Label + Nome da Entidade string developer global Payload Monitor - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2788,7 +2788,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2797,7 +2797,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2808,31 +2808,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global maneuver - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global user - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean user maneuver 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário Payload timeout @@ -2848,7 +2848,7 @@ list:string developer global - EstimatedState:Navigation Manager, Temperature:CTD, Temperature:AirMar120WX, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager + EstimatedState:Navigation Manager, Temperature:CTD, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager List of messages <Message>:<Entity> to send using Iridium. @@ -2873,25 +2873,25 @@
- Entity Label + Nome da Entidade string developer global Wave Frequency Estimator - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -2900,7 +2900,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -2909,7 +2909,7 @@ - Debug Level + Nível de Depuração string developer global @@ -2920,7 +2920,7 @@ None, Debug, Trace, Spew - Active + Ativa boolean developer global @@ -3042,25 +3042,25 @@
- Entity Label + Nome da Entidade string developer global Navigation Manager - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -3069,7 +3069,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -3078,7 +3078,7 @@ - Debug Level + Nível de Depuração string developer global @@ -3162,27 +3162,27 @@ Distance needed for reference change.
-
+
- Entity Label + Nome da Entidade string developer global Plan Database - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -3191,7 +3191,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -3200,7 +3200,7 @@ - Debug Level + Nível de Depuração string developer global @@ -3220,27 +3220,27 @@ Path to DB file
-
+
- Entity Label + Nome da Entidade string developer global Plan Engine - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -3249,7 +3249,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -3258,7 +3258,7 @@ - Debug Level + Nível de Depuração string developer global @@ -3368,27 +3368,27 @@ Entity label of the Plan Generator
-
+
- Entity Label + Nome da Entidade string developer global Plan Generator - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -3397,7 +3397,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -3406,7 +3406,7 @@ - Debug Level + Nível de Depuração string developer global @@ -3473,25 +3473,25 @@
- Entity Label + Nome da Entidade string developer global CPC - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -3500,7 +3500,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -3509,7 +3509,7 @@ - Debug Level + Nível de Depuração string developer global @@ -3520,31 +3520,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global developer - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean developer global 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário IO Port - Device @@ -4197,25 +4197,25 @@
- Entity Label + Nome da Entidade string developer global AIS - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -4224,7 +4224,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -4233,7 +4233,7 @@ - Debug Level + Nível de Depuração string developer global @@ -4244,31 +4244,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global developer - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean developer global 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário IO Port - Device @@ -4427,25 +4427,25 @@
- Entity Label + Nome da Entidade string developer global AirMar120WX - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -4454,7 +4454,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -4463,7 +4463,7 @@ - Debug Level + Nível de Depuração string developer global @@ -4474,31 +4474,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global developer - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean developer global 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário IO Port - Device @@ -4531,25 +4531,25 @@
- Entity Label + Nome da Entidade string developer global Fluorometers - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -4558,7 +4558,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -4567,7 +4567,7 @@ - Debug Level + Nível de Depuração string developer global @@ -4578,31 +4578,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global maneuver - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global user - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean user maneuver 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário Serial Port - Device @@ -4725,25 +4725,25 @@
- Entity Label + Nome da Entidade string developer global GPS - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -4752,7 +4752,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -4761,7 +4761,7 @@ - Debug Level + Nível de Depuração string developer global @@ -4772,31 +4772,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global developer - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean developer global 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário IO Port - Device @@ -5020,25 +5020,25 @@
- Entity Label + Nome da Entidade string developer global AHRS - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -5047,7 +5047,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -5056,7 +5056,7 @@ - Debug Level + Nível de Depuração string developer global @@ -5067,31 +5067,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global developer - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean developer global 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário IO Port - Device @@ -5183,25 +5183,25 @@
- Entity Label + Nome da Entidade string developer global ADCP - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -5210,7 +5210,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -5219,7 +5219,7 @@ - Debug Level + Nível de Depuração string developer global @@ -5230,31 +5230,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global developer - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean developer global 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário IO Port - Device @@ -5394,25 +5394,25 @@
- Entity Label + Nome da Entidade string developer global Dissolved Oxygen - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 20 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -5421,7 +5421,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -5430,7 +5430,7 @@ - Debug Level + Nível de Depuração string developer global @@ -5441,31 +5441,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global developer - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean developer global 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário IO Port - Device @@ -5569,25 +5569,25 @@
- Entity Label + Nome da Entidade string developer global CTD - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -5596,7 +5596,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -5605,7 +5605,7 @@ - Debug Level + Nível de Depuração string developer global @@ -5616,31 +5616,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global maneuver - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global user - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean user maneuver 1 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário IO Port - Device @@ -5706,27 +5706,27 @@ Input timeout in seconds. Must be greater than 2*Sample Time Duration
-
+
- Entity Label + Nome da Entidade string developer global Thermal Zone - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -5735,7 +5735,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -5744,7 +5744,7 @@ - Debug Level + Nível de Depuração string developer global @@ -5755,13 +5755,13 @@ None, Debug, Trace, Spew - Execution Frequency + Frequência de Execução real developer global 1 Hz - Frequency at which task is executed + Frequência com que a tarefa é executada Path @@ -5784,25 +5784,25 @@
- Entity Label + Nome da Entidade string developer global Autonaut Supervisor - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -5811,7 +5811,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -5820,7 +5820,7 @@ - Debug Level + Nível de Depuração string developer global @@ -5831,13 +5831,13 @@ None, Debug, Trace, Spew - Execution Frequency + Frequência de Execução real developer global 2 Hz - Frequency at which task is executed + Frequência com que a tarefa é executada Loiter On Service -- Radius @@ -5860,27 +5860,27 @@ 0.1
-
+
- Entity Label + Nome da Entidade string developer global Power Supervisor - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -5889,7 +5889,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -5898,7 +5898,7 @@ - Debug Level + Nível de Depuração string developer global @@ -5945,27 +5945,27 @@ Name of the slave systems
-
+
- Entity Label + Nome da Entidade string developer global Report Supervisor - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -5974,7 +5974,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -5983,7 +5983,7 @@ - Debug Level + Nível de Depuração string developer global @@ -5994,7 +5994,7 @@ None, Debug, Trace, Spew - Acoustic Reports + Relatórios Acústicos boolean user global @@ -6003,7 +6003,7 @@ Enable acoustic system state reporting - Acoustic Reports Periodicity + Periodicidade de Relatórios Acústicos real user global @@ -6014,7 +6014,7 @@ 600 - Radio Reports + Relatórios de Rádio boolean user global @@ -6023,7 +6023,7 @@ Enable Radio system state reporting - Radio Reports Periodicity + Periodicidade de relatórios de rádio real user global @@ -6034,27 +6034,27 @@ 600
-
+
- Entity Label + Nome da Entidade string developer global Vehicle Supervisor - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6063,7 +6063,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6072,7 +6072,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6083,13 +6083,13 @@ None, Debug, Trace, Spew - Execution Frequency + Frequência de Execução real developer global 2 Hz - Frequency at which task is executed + Frequência com que a tarefa é executada Vital Entities @@ -6119,27 +6119,27 @@ Timeout for starting or stopping a maneuver
-
+
- Entity Label + Nome da Entidade string developer global Service Announcer - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6148,7 +6148,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6157,7 +6157,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6258,27 +6258,27 @@ List of interfaces whose services will not be announced
-
+
- Entity Label + Nome da Entidade string developer global Cache - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6287,7 +6287,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6296,7 +6296,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6316,27 +6316,27 @@ List of messages ordered by loading order
-
+
- Entity Label + Nome da Entidade string developer global Communications Manager - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6345,7 +6345,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6354,7 +6354,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6428,27 +6428,27 @@ Send Iridium text messages as plain text (and not IMC)
-
+
- Entity Label + Nome da Entidade string developer global Service Discovery - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6457,7 +6457,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6466,7 +6466,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6504,27 +6504,27 @@ Print incoming messages (Debug)
-
+
- Entity Label + Nome da Entidade string developer global FTP Server - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6533,7 +6533,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6542,7 +6542,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6580,27 +6580,27 @@ Timeout period of a session
-
+
- Entity Label + Nome da Entidade string developer global Message Fragments - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6609,7 +6609,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6618,7 +6618,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6640,25 +6640,25 @@
- Entity Label + Nome da Entidade string developer global GSM - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6667,7 +6667,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6676,7 +6676,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6777,27 +6777,27 @@ Balance Periodicity
-
+
- Entity Label + Nome da Entidade string developer global HTTP Server - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6806,7 +6806,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6815,7 +6815,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6853,27 +6853,27 @@ List of messages to transport
-
+
- Entity Label + Nome da Entidade string developer global Iridium Transport - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6882,7 +6882,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -6891,7 +6891,7 @@ - Debug Level + Nível de Depuração string developer global @@ -6902,31 +6902,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global user - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean user global true - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário Device updates - Periodicity @@ -6967,25 +6967,25 @@
- Entity Label + Nome da Entidade string developer global Iridium Operation - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -6994,7 +6994,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -7003,7 +7003,7 @@ - Debug Level + Nível de Depuração string developer global @@ -7014,31 +7014,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global user - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean user global 0 - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário Maximum iridium payload size @@ -7095,27 +7095,27 @@ Iridium operation timeout in seconds.
-
+
- Entity Label + Nome da Entidade string developer global Iridium Modem - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -7124,7 +7124,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -7133,7 +7133,7 @@ - Debug Level + Nível de Depuração string developer global @@ -7144,31 +7144,31 @@ None, Debug, Trace, Spew - Active - Scope + Ativa - Escopo string developer global global - Scoped of the 'Active' parameter + Escopo do parâmetro 'Ativa' - Active - Visibility + Ativa - Visibilidade string developer global user - Visibility of the 'Active' parameter + Visibilidade do parâmetro 'Ativa' - Active + Ativa boolean user global true - True to activate task, false otherwise + Verdadeiro para ativar tarefa, falso caso contrário Serial Port - Device @@ -7263,27 +7263,27 @@ 5
-
+
- Entity Label + Nome da Entidade string developer global Log Book - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -7292,7 +7292,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -7301,7 +7301,7 @@ - Debug Level + Nível de Depuração string developer global @@ -7312,27 +7312,27 @@ None, Debug, Trace, Spew
-
+
- Entity Label + Nome da Entidade string developer global Logger - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 2 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -7341,7 +7341,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -7350,7 +7350,7 @@ - Debug Level + Nível de Depuração string developer global @@ -7408,25 +7408,25 @@
- Entity Label + Nome da Entidade string developer global UDP - Main entity label + Nome principal da entidade - Execution Priority + Prioridade de Execução integer developer global 10 - Execution priority + Prioridade de execução - Activation Time + Tempo de Ativação integer developer global @@ -7435,7 +7435,7 @@ - Deactivation Time + Tempo de Desativação integer developer global @@ -7444,7 +7444,7 @@ - Debug Level + Nível de Depuração string developer global From 6ee3573591b457a57cae4e97762a90efae257ba0 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 2 Aug 2024 18:43:03 +0100 Subject: [PATCH 44/92] conf/params/caravel: Updated parameters. # Conflicts: # conf/params/caravel.en_US.xml # conf/params/caravel.pt_PT.xml --- conf/params/caravel.en_US.xml | 8 ++++---- conf/params/caravel.pt_PT.xml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 5a5c327ab3..5ea35e5303 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -909,7 +909,7 @@ boolean developer global - true + false Enable collision avoidance algorithm @@ -918,7 +918,7 @@ boolean developer global - true + false Enable anti-grounding algorithm @@ -2848,7 +2848,7 @@ list:string developer global - + EstimatedState:Navigation Manager, Temperature:CTD, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager List of messages <Message>:<Entity> to send using Iridium. diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index 7960bb4988..aa0917178b 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -909,7 +909,7 @@ boolean developer global - true + false Enable collision avoidance algorithm @@ -918,7 +918,7 @@ boolean developer global - true + false Enable anti-grounding algorithm @@ -2848,7 +2848,7 @@ list:string developer global - + EstimatedState:Navigation Manager, Temperature:CTD, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager List of messages <Message>:<Entity> to send using Iridium. From 1d2e83aebe72586dea4ae2f09345c751203c4df7 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 20 Aug 2024 13:06:13 +0100 Subject: [PATCH 45/92] comm/iridium/ImcFullIridiumMessage: Fix obfuscated msg variable by mistake. --- src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java b/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java index 7437961fb4..81f2903e91 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java @@ -46,8 +46,6 @@ */ public class ImcFullIridiumMessage extends ImcIridiumMessage { - protected IMCMessage msg; - // 5 bytes for RB addressing, 6 bytes for type and timestamp, 6 bytes for IMC header public static int MaxPayloadSize = 270 - 17; From d787dba5e96f53583931fe0cef0ffb59a04d8c5b Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 20 Aug 2024 13:07:11 +0100 Subject: [PATCH 46/92] plugins/sunfish/iridium/feedback/IridiumStatusTableModel: Fix for potential exception. --- .../feedback/IridiumStatusTableModel.java | 110 ++++++++++-------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatusTableModel.java b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatusTableModel.java index 714c1e3941..b4714b5333 100644 --- a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatusTableModel.java +++ b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatusTableModel.java @@ -210,59 +210,71 @@ public int getColumnCount() { @Override public Object getValueAt(int rowIndex, int columnIndex) { + try { + IridiumMessage m = msgs.get(rowIndex); - IridiumMessage m = msgs.get(rowIndex); - - String messageType = m.getMessageType() == 0 ? "Custom Iridium Message" : m.getClass().getSimpleName(); - int src = m.getSource(); - int dst = m.getDestination(); + String messageType = m.getMessageType() == 0 ? "Custom Iridium Message" : m.getClass().getSimpleName(); + int src = m.getSource(); + int dst = m.getDestination(); - switch (columnIndex) { - case TIMESTAMP: - { - if(messageType.equalsIgnoreCase("ImcIridiumMessage") || - messageType.equalsIgnoreCase("ImcFullIridiumMessage")) { - IMCMessage msg = ((ImcIridiumMessage) m).getMsg(); - if(msg.getMgid() == StateReport.ID_STATIC) { - long stime = ((StateReport) msg).getStime() * 1000; - TimeZone.getTimeZone(TimeZone.getDefault().getID()); - StringBuilder sb = new StringBuilder("V "); - sb.append(sdf.format(new Date(stime))); + switch (columnIndex) { + case TIMESTAMP: { + try { + if (messageType.equalsIgnoreCase("ImcIridiumMessage") || + messageType.equalsIgnoreCase("ImcFullIridiumMessage")) { + IMCMessage msg = ((ImcIridiumMessage) m).getMsg(); + if (msg.getMgid() == StateReport.ID_STATIC) { + long stime = ((StateReport) msg).getStime() * 1000; + TimeZone.getTimeZone(TimeZone.getDefault().getID()); + StringBuilder sb = new StringBuilder("V "); + sb.append(sdf.format(new Date(stime))); + return sb.toString(); + } + } + StringBuilder sb = new StringBuilder("M "); + sb.append(sdf.format(new Date(m.timestampMillis))); return sb.toString(); } + catch (Exception e) { + NeptusLog.pub().warn("?? " + messageType + " " + m + " :: " + e.getMessage()); + return "?? " + messageType + " " + m; + } } - StringBuilder sb = new StringBuilder("M "); - sb.append(sdf.format(new Date(m.timestampMillis))); - return sb.toString(); - } - case SYSTEM: - return IMCDefinition.getInstance().getResolver().resolve(src); - case STATUS: - if (status.containsKey(rowIndex)) { - return status.get(rowIndex)._status; - } - /* - * else if(src == ImcMsgManager.getManager().getLocalId().intValue()) return IridiumCommsStatus.SENT; - */ - if(messageType.equalsIgnoreCase("IridiumCommand")) { - IridiumCommand cmd = (IridiumCommand) m; - String txt = cmd.getCommand(); - if(txt.startsWith("ERROR")) - return IridiumCommsStatus.ERROR; + case SYSTEM: + return IMCDefinition.getInstance().getResolver().resolve(src); + case STATUS: + if (status.containsKey(rowIndex)) { + return status.get(rowIndex)._status; + } + /* + * else if(src == ImcMsgManager.getManager().getLocalId().intValue()) return IridiumCommsStatus.SENT; + */ + if (messageType.equalsIgnoreCase("IridiumCommand")) { + IridiumCommand cmd = (IridiumCommand) m; + String txt = cmd.getCommand(); + if (txt.startsWith("ERROR")) + return IridiumCommsStatus.ERROR; - } - else if (dst == 65535 || dst == ImcMsgManager.getManager().getLocalId().intValue()) { // dst - 65535 - 255 // - broadcast - return IridiumCommsStatus.DELIVERED; - } + } + else if (dst == 65535 || dst == ImcMsgManager.getManager().getLocalId().intValue()) { // dst - 65535 - 255 // - broadcast + return IridiumCommsStatus.DELIVERED; + } return IridiumCommsStatus.UNCERTAIN; - case MSG_TYPE: - if(messageType.equalsIgnoreCase("ImcIridiumMessage") || - messageType.equalsIgnoreCase("ImcFullIridiumMessage")) - return ((ImcIridiumMessage) m).getMsg().getClass().getSimpleName(); - else - return messageType; - default: - return "??"; + case MSG_TYPE: + try { + if (messageType.equalsIgnoreCase("ImcIridiumMessage") || + messageType.equalsIgnoreCase("ImcFullIridiumMessage")) + return ((ImcIridiumMessage) m).getMsg().getClass().getSimpleName(); + else + return messageType; + } catch (Exception e) { + return "::" + messageType; + } + default: + return "??"; + } + } catch (Exception e) { + return "?? " + rowIndex + " " + columnIndex + " " + e.getMessage(); } } @@ -299,13 +311,15 @@ else if(date.startsWith("M ")) { * @param milis - milliseconds */ public void cleanupAfter(long millis) { - msgs.removeIf(msg -> (System.currentTimeMillis() - msg.timestampMillis) > millis); + synchronized (msgs) { + msgs.removeIf(msg -> (System.currentTimeMillis() - msg.timestampMillis) > millis); + } fireTableDataChanged(); } } /** - * Iridium Local Transmissions Status + * Iridium Local Transmissions StatusTDefaultRowSorter * */ class TransmissionStatus { From 77aa5f80fb2a11d583bb6a6b9c3e8ec8cfb6db91 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 20 Aug 2024 13:07:26 +0100 Subject: [PATCH 47/92] plugins/sunfish/iridium/feedback/IridiumStatus: Fix for potential exception. --- .../sunfish/iridium/feedback/IridiumStatus.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatus.java b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatus.java index eabf841e9a..77b2a5091d 100644 --- a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatus.java +++ b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/iridium/feedback/IridiumStatus.java @@ -187,6 +187,16 @@ public void run() { @Override public int compare(String sdf1, String sdf2) { + if (sdf1 == null && sdf2 == null) { + return 0; + } + else if (sdf1 == null) { + return -1; + } + else if (sdf2 == null) { + return 1; + } + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS dd-MM-yyyy 'Z'"); sdf1 = sdf1.replaceAll("V ", ""); sdf2 = sdf2.replaceAll("V ", ""); From 76a7ae5d182f7a76d86a449937e441eaf7b238ff Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 20 Aug 2024 16:47:05 +0100 Subject: [PATCH 48/92] console/plugins/AbortPanel: Fir for new channel comms (still needs to clean the popup msgs). --- .../neptus/console/plugins/AbortPanel.java | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/AbortPanel.java b/src/java/pt/lsts/neptus/console/plugins/AbortPanel.java index 44494d5839..0e106193c6 100644 --- a/src/java/pt/lsts/neptus/console/plugins/AbortPanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/AbortPanel.java @@ -58,8 +58,11 @@ import pt.lsts.imc.Abort; import pt.lsts.imc.IMCMessage; import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.comm.IMCSendMessageUtils; +import pt.lsts.neptus.comm.manager.imc.ImcMsgManager; import pt.lsts.neptus.comm.manager.imc.ImcSystem; import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; +import pt.lsts.neptus.comm.manager.imc.MessageDeliveryListener; import pt.lsts.neptus.console.ConsoleLayout; import pt.lsts.neptus.console.ConsolePanel; import pt.lsts.neptus.console.notifications.Notification; @@ -249,7 +252,11 @@ public void actionPerformed(final ActionEvent e) { SwingWorker worker = new SwingWorker() { @Override protected Void doInBackground() throws Exception { - send(new IMCMessage("Abort")); + // send(new IMCMessage("Abort")); + IMCSendMessageUtils.sendMessage(new IMCMessage("Abort"), ImcMsgManager.TRANSPORT_TCP, + createDefaultMessageDeliveryListener(), getConsole(), "", true, + "", true, true, true, + getConsole().getMainSystem()); boolean sentToAll = false; if ((e.getModifiers() & ActionEvent.CTRL_MASK) != 0) { @@ -318,6 +325,48 @@ protected void done() { return abortAction; } + private MessageDeliveryListener createDefaultMessageDeliveryListener() { + return new MessageDeliveryListener() { + private String getDest(IMCMessage message) { + ImcSystem sys = message != null ? ImcSystemsHolder.lookupSystem(message.getDst()) : null; + String dest = sys != null ? sys.getName() : I18n.text("unknown destination"); + return dest; + } + + @Override + public void deliveryUnreacheable(IMCMessage message) { + post(Notification.error( + I18n.text("Delivering Message"), + I18n.textf("Message %messageType to %destination delivery destination unreacheable", + message.getAbbrev(), getDest(message)))); + } + + @Override + public void deliveryTimeOut(IMCMessage message) { + post(Notification.error( + I18n.text("Delivering Message"), + I18n.textf("Message %messageType to %destination delivery timeout", + message.getAbbrev(), getDest(message)))); + } + + @Override + public void deliveryError(IMCMessage message, Object error) { + post(Notification.error( + I18n.text("Delivering Message"), + I18n.textf("Message %messageType to %destination delivery error. (%error)", + message.getAbbrev(), getDest(message), error))); + } + + @Override + public void deliveryUncertain(IMCMessage message, Object msg) { + } + + @Override + public void deliverySuccess(IMCMessage message) { + } + }; + } + @Override public boolean isLocked() { return !getAbortButton().isEnabled(); From 5b9302c4dd83ad5db437ffc9c21d3fdcd6d8b31d Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 21 Aug 2024 14:03:08 +0100 Subject: [PATCH 49/92] console/plugins/EntityStatePanel: Adding speak on entity change. --- .../console/plugins/EntityStatePanel.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/EntityStatePanel.java b/src/java/pt/lsts/neptus/console/plugins/EntityStatePanel.java index e0f318a5f9..afb76605e6 100644 --- a/src/java/pt/lsts/neptus/console/plugins/EntityStatePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/EntityStatePanel.java @@ -38,6 +38,7 @@ import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; +import java.time.Duration; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Timer; @@ -54,7 +55,6 @@ import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; -import javax.swing.text.html.parser.Entity; import com.google.common.eventbus.Subscribe; @@ -81,6 +81,7 @@ import pt.lsts.neptus.plugins.Popup.POSITION; import pt.lsts.neptus.util.DateTimeUtil; import pt.lsts.neptus.util.ImageUtils; +import pt.lsts.neptus.util.speech.SpeechUtil; /** * @author pdias @@ -114,6 +115,8 @@ public class EntityStatePanel extends ConsolePanel implements NeptusMessageListe private JTable table = null; private StatusLed status; + private long timeSinceLastUpdateVoiceWarning = -1; + /** * @param console */ @@ -375,11 +378,14 @@ public void messageArrived(IMCMessage message) { EntityStateType eType = dataMap.get(entityName); Integer index = eType == null ? null : data.indexOf(eType); + boolean wasChange = false; + // Updating (not the first time receiving for this entity) if (index != null) { eType = data.get(index); if (message.getLong("state") != eType.getState().longValue()) { // Means it has changed, time to post a -// msg_type type = msg_type.info; + // msg_type type = msg_type.info; + wasChange = true; } eType.update(entityName, new Enumerated(message.getMessageType().getFieldPossibleValues("state"), message.getLong("state")), message.getString("description"), System.currentTimeMillis()); @@ -387,6 +393,7 @@ public void messageArrived(IMCMessage message) { etmodel.fireTableRowsUpdated(index, index); } else { + wasChange = true; eType = new EntityStateType(entityName, new Enumerated(message.getMessageType().getFieldPossibleValues( "state"), message.getLong("state")), getDescription(), System.currentTimeMillis()); @@ -397,6 +404,9 @@ public void messageArrived(IMCMessage message) { } } calcTotalState(); + + if (wasChange) + speakUpdateEntityState(); } } @@ -416,6 +426,14 @@ void sendEntityListRequestMsg() { } } + private synchronized void speakUpdateEntityState() { + if (System.currentTimeMillis() - timeSinceLastUpdateVoiceWarning > Duration.ofSeconds(10).toMillis()) { + timeSinceLastUpdateVoiceWarning = System.currentTimeMillis(); + String msg = I18n.text("Entity state"); + SpeechUtil.readSimpleText(msg); + } + } + private MessageDeliveryListener createDefaultMessageDeliveryListener() { return (new MessageDeliveryListener() { From 3701f2ba14148645d1649ffc60eec685070358d5 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 21 Aug 2024 14:03:50 +0100 Subject: [PATCH 50/92] console/comm/iridium/IridiumManager: Adding speak on new message. --- .../neptus/comm/iridium/IridiumManager.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java index a091a9e822..76ed294c45 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java @@ -54,9 +54,11 @@ import pt.lsts.imc.net.IMCFragmentHandler; import pt.lsts.neptus.NeptusLog; import pt.lsts.neptus.comm.manager.imc.ImcMsgManager; +import pt.lsts.neptus.i18n.I18n; import pt.lsts.neptus.util.ByteUtil; import pt.lsts.neptus.util.ImageUtils; import pt.lsts.neptus.util.conf.GeneralPreferences; +import pt.lsts.neptus.util.speech.SpeechUtil; /** * This class will handle Iridium communications @@ -75,6 +77,8 @@ public class IridiumManager { public static final int IRIDIUM_MTU = 270; public static final int IRIDIUM_HEADER = 6; + + private long timeSinceLastUpdateVoiceWarning = -1; public enum IridiumMessengerEnum { DuneIridiumMessenger, @@ -111,8 +115,12 @@ public void run() { try { Date now = new Date(); Collection msgs = getCurrentMessenger().pollMessages(lastTime); - for (IridiumMessage m : msgs) + if (!msgs.isEmpty()) { + speakUpdateEntityState(); + } + for (IridiumMessage m : msgs) { processMessage(m); + } lastTime = now; } @@ -122,7 +130,15 @@ public void run() { } } }; - + + private synchronized void speakUpdateEntityState() { + if (System.currentTimeMillis() - timeSinceLastUpdateVoiceWarning > Duration.ofSeconds(10).toMillis()) { + timeSinceLastUpdateVoiceWarning = System.currentTimeMillis(); + String msg = I18n.text("Ireedeehum received"); // To be able to speak Iridium + SpeechUtil.readSimpleText(msg); + } + } + public boolean isAvailable() { return getCurrentMessenger().isAvailable(); } From b5286e2d5502c1a0fdbc5332fd08ce3152da3144 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 23 Aug 2024 17:30:54 +0100 Subject: [PATCH 51/92] conf/params/caravel: Updated parameters. --- conf/params/caravel.en_US.xml | 57 ++++++++++++++++++++++++++--------- conf/params/caravel.pt_PT.xml | 57 ++++++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 30 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 5ea35e5303..270f97cc7e 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -907,7 +907,7 @@ Enable Collision Avoidance boolean - developer + user global false @@ -916,7 +916,7 @@ Enable Anti Grounding boolean - developer + user global false @@ -3093,7 +3093,7 @@ string developer global - GPS + AHRS Entity label of 'GpsFix' and 'GroundVelocity' messages @@ -3902,7 +3902,7 @@ string developer global - CTD_P + Private (CTD_P) Power Channel Entity Label @@ -5620,7 +5620,7 @@ string developer global - maneuver + global Scoped of the 'Active' parameter @@ -5629,15 +5629,15 @@ string developer global - user + developer Visibility of the 'Active' parameter Active boolean - user - maneuver + developer + global 1 True to activate task, false otherwise @@ -5658,7 +5658,16 @@ global 125 ms - Sample period in milliseconds + Sample Period in milliseconds + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. Sample Time Duration @@ -5705,6 +5714,24 @@ Input timeout in seconds. Must be greater than 2*Sample Time Duration + + Medium Threshold + real + developer + global + 0.2 + + Medium conductivity threshold. + + + Medium Periodicity + real + developer + global + 1.0 + + Medium dispatch periodicity. +
@@ -6244,7 +6271,7 @@ string developer global - + usv System type @@ -7081,7 +7108,7 @@ integer developer global - 120 + 240 Time to live for iridium messages. @@ -7090,7 +7117,7 @@ integer developer global - 600 + 1200 Iridium operation timeout in seconds. @@ -7247,7 +7274,7 @@ real user global - 100 + 300 Window to prioritize Transmission over Reception 5 @@ -7257,7 +7284,7 @@ real user global - 100 + 60 Window to prioritize Reception over Transmission 5 diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index aa0917178b..92f3c6cec2 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -907,7 +907,7 @@ Enable Collision Avoidance boolean - developer + user global false @@ -916,7 +916,7 @@ Enable Anti Grounding boolean - developer + user global false @@ -3093,7 +3093,7 @@ string developer global - GPS + AHRS Entity label of 'GpsFix' and 'GroundVelocity' messages @@ -3902,7 +3902,7 @@ string developer global - CTD_P + Private (CTD_P) Power Channel Entity Label @@ -5620,7 +5620,7 @@ string developer global - maneuver + global Escopo do parâmetro 'Ativa' @@ -5629,15 +5629,15 @@ string developer global - user + developer Visibilidade do parâmetro 'Ativa' Ativa boolean - user - maneuver + developer + global 1 Verdadeiro para ativar tarefa, falso caso contrário @@ -5658,7 +5658,16 @@ global 125 ms - Sample period in milliseconds + Sample Period in milliseconds + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. Sample Time Duration @@ -5705,6 +5714,24 @@ Input timeout in seconds. Must be greater than 2*Sample Time Duration + + Medium Threshold + real + developer + global + 0.2 + + Medium conductivity threshold. + + + Medium Periodicity + real + developer + global + 1.0 + + Medium dispatch periodicity. +
@@ -6244,7 +6271,7 @@ string developer global - + usv System type @@ -7081,7 +7108,7 @@ integer developer global - 120 + 240 Time to live for iridium messages. @@ -7090,7 +7117,7 @@ integer developer global - 600 + 1200 Iridium operation timeout in seconds. @@ -7247,7 +7274,7 @@ real user global - 100 + 300 Window to prioritize Transmission over Reception 5 @@ -7257,7 +7284,7 @@ real user global - 100 + 60 Window to prioritize Reception over Transmission 5 From f6512652d6848a565a7e58ab2f70d8462b0f7e47 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 23 Aug 2024 17:30:54 +0100 Subject: [PATCH 52/92] conf/params/caravel: Updated parameters. --- conf/params/caravel.en_US.xml | 57 ++++++++++++++++++++++++++--------- conf/params/caravel.pt_PT.xml | 57 ++++++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 30 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 5ea35e5303..270f97cc7e 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +
Entity Label @@ -907,7 +907,7 @@ Enable Collision Avoidance boolean - developer + user global false @@ -916,7 +916,7 @@ Enable Anti Grounding boolean - developer + user global false @@ -3093,7 +3093,7 @@ string developer global - GPS + AHRS Entity label of 'GpsFix' and 'GroundVelocity' messages @@ -3902,7 +3902,7 @@ string developer global - CTD_P + Private (CTD_P) Power Channel Entity Label @@ -5620,7 +5620,7 @@ string developer global - maneuver + global Scoped of the 'Active' parameter @@ -5629,15 +5629,15 @@ string developer global - user + developer Visibility of the 'Active' parameter Active boolean - user - maneuver + developer + global 1 True to activate task, false otherwise @@ -5658,7 +5658,16 @@ global 125 ms - Sample period in milliseconds + Sample Period in milliseconds + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. Sample Time Duration @@ -5705,6 +5714,24 @@ Input timeout in seconds. Must be greater than 2*Sample Time Duration + + Medium Threshold + real + developer + global + 0.2 + + Medium conductivity threshold. + + + Medium Periodicity + real + developer + global + 1.0 + + Medium dispatch periodicity. +
@@ -6244,7 +6271,7 @@ string developer global - + usv System type @@ -7081,7 +7108,7 @@ integer developer global - 120 + 240 Time to live for iridium messages. @@ -7090,7 +7117,7 @@ integer developer global - 600 + 1200 Iridium operation timeout in seconds. @@ -7247,7 +7274,7 @@ real user global - 100 + 300 Window to prioritize Transmission over Reception 5 @@ -7257,7 +7284,7 @@ real user global - 100 + 60 Window to prioritize Reception over Transmission 5 diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index aa0917178b..92f3c6cec2 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -907,7 +907,7 @@ Enable Collision Avoidance boolean - developer + user global false @@ -916,7 +916,7 @@ Enable Anti Grounding boolean - developer + user global false @@ -3093,7 +3093,7 @@ string developer global - GPS + AHRS Entity label of 'GpsFix' and 'GroundVelocity' messages @@ -3902,7 +3902,7 @@ string developer global - CTD_P + Private (CTD_P) Power Channel Entity Label @@ -5620,7 +5620,7 @@ string developer global - maneuver + global Escopo do parâmetro 'Ativa' @@ -5629,15 +5629,15 @@ string developer global - user + developer Visibilidade do parâmetro 'Ativa' Ativa boolean - user - maneuver + developer + global 1 Verdadeiro para ativar tarefa, falso caso contrário @@ -5658,7 +5658,16 @@ global 125 ms - Sample period in milliseconds + Sample Period in milliseconds + + + Start Acquisition + boolean + user + maneuver + false + + Start Acquisition. Sample Time Duration @@ -5705,6 +5714,24 @@ Input timeout in seconds. Must be greater than 2*Sample Time Duration + + Medium Threshold + real + developer + global + 0.2 + + Medium conductivity threshold. + + + Medium Periodicity + real + developer + global + 1.0 + + Medium dispatch periodicity. +
@@ -6244,7 +6271,7 @@ string developer global - + usv System type @@ -7081,7 +7108,7 @@ integer developer global - 120 + 240 Time to live for iridium messages. @@ -7090,7 +7117,7 @@ integer developer global - 600 + 1200 Iridium operation timeout in seconds. @@ -7247,7 +7274,7 @@ real user global - 100 + 300 Window to prioritize Transmission over Reception 5 @@ -7257,7 +7284,7 @@ real user global - 100 + 60 Window to prioritize Reception over Transmission 5 From 43cea6e4f36037427ba88409c28c7d578f8e11d2 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 14 Nov 2024 15:28:28 +0000 Subject: [PATCH 53/92] comm/manager/imc/ImcMsgManagerMessageProcessor: Fix processing heading on StateReport message. --- .../neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java index 8fa9abf6be..e6a389258c 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java @@ -145,7 +145,7 @@ void processStateReport(MessageInfo info, StateReport msg, ArrayList double lon = msg.getLongitude(); double depth = msg.getDepth() == 0xFFFF ? -1 : msg.getDepth() / 10.0; // double altitude = msg.getAltitude() == 0xFFFF ? -1 : msg.getAltitude() / 10.0; - double heading = ((double)msg.getHeading() / 65535.0) * 360; + double heading = Math.toDegrees(AngleUtils.nomalizeAngleRads2Pi(((double) msg.getHeading() / 65535.0) * Math.PI * 2)); double speedMS = msg.getSpeed() / 100.; NeptusLog.pub().info("Received report from "+msg.getSourceName()); From c70e5f76a2c9f8a621bfc7894d4762e5b7c39eb5 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 14 Nov 2024 15:32:55 +0000 Subject: [PATCH 54/92] comm/manager/imc/ImcMsgManagerAnnounceProcessor: Avoiding depth=-height on locations created. --- .../neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java index 319a23b5c0..80b744a5c6 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java @@ -312,6 +312,7 @@ else if (portTcp == 0) { loc.setLatitudeDegs(Math.toDegrees(latRad)); loc.setLongitudeDegs(Math.toDegrees(lonRad)); loc.setHeight(height); + loc.setDepth(-1); long locTime = (long) (info.getTimeSentSec() * 1000); resSys.setLocation(loc, locTime); } From 4b68231ef14837c92ad648732b799344561c2082 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 15 Nov 2024 17:22:33 +0000 Subject: [PATCH 55/92] lib/libimc.jar: Updated to LSTS/imc@76cc63e and LSTS/imcjava@eb600cb compiled with Java 8. --- build.gradle | 4 ++-- lib/{libimc-5.90.2.jar => libimc-5.90.4.jar} | Bin 2359159 -> 2392493 bytes ...der-5.90.2.jar => libimcsender-5.90.4.jar} | Bin 1351364 -> 1351378 bytes 3 files changed, 2 insertions(+), 2 deletions(-) rename lib/{libimc-5.90.2.jar => libimc-5.90.4.jar} (86%) rename lib/{libimcsender-5.90.2.jar => libimcsender-5.90.4.jar} (96%) diff --git a/build.gradle b/build.gradle index 051d53c6d9..5563a7b944 100644 --- a/build.gradle +++ b/build.gradle @@ -349,8 +349,8 @@ project(':core') { } dependencies { - implementation name: 'libimc-5.90.2' - implementation name: 'libimcsender-5.90.2' + implementation name: 'libimc-5.90.4' + implementation name: 'libimcsender-5.90.4' implementation name: 'aisparser-2.0.0' implementation name: 'jssc' //dependency of aisparser, and serial port reader diff --git a/lib/libimc-5.90.2.jar b/lib/libimc-5.90.4.jar similarity index 86% rename from lib/libimc-5.90.2.jar rename to lib/libimc-5.90.4.jar index d903227c4d2406f9957a7b20a7ba09ed00ed2d21..f5b5afe63548c036e36bf4451dfec055066a8c97 100644 GIT binary patch delta 249973 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

Q!2s=93Ff)rm(%U;ar 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 z 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 VX|Z@aymV;%Wz{MnW9V4<{{a&*CJ6ul diff --git a/lib/libimcsender-5.90.2.jar b/lib/libimcsender-5.90.4.jar similarity index 96% rename from lib/libimcsender-5.90.2.jar rename to lib/libimcsender-5.90.4.jar index be8a65ab5409842ceafdec800d762f599a24ead9..e626e6f27be666fcb87a9d63bb0892cca84cafe6 100644 GIT binary patch delta 13185 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 HIw<}R&C#K& From b53c6ed4b14a0d08037c074c77e4da1712d66694 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 15 Nov 2024 17:37:09 +0000 Subject: [PATCH 56/92] conf/params/caravel: Updated parameters. --- conf/params/caravel.en_US.xml | 703 ++++++++++++++++++++++++++-------- conf/params/caravel.pt_PT.xml | 703 ++++++++++++++++++++++++++-------- 2 files changed, 1084 insertions(+), 322 deletions(-) diff --git a/conf/params/caravel.en_US.xml b/conf/params/caravel.en_US.xml index 270f97cc7e..f9a5c13c39 100644 --- a/conf/params/caravel.en_US.xml +++ b/conf/params/caravel.en_US.xml @@ -1,5 +1,5 @@ - +

Entity Label @@ -2108,6 +2108,102 @@ None, Debug, Trace, Spew
+
+ + Entity Label + string + developer + global + Boot Monitor + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Boot Message Delay + real + developer + global + 10 + + Delay, in seconds, before dispatching boot message. Value can not be less than 1s. + 1 + + + Boot Message TTL + real + developer + global + 300 + + Boot message time-to-live, in seconds. Value can not be less than 60s. + 60 + + + Default SMS Recipient Number + string + user + global + + + Phone number of the SMS recipient + + + Task Label for SMS Number + string + user + global + Monitors.Emergency + + Task Label for SMS Number + + + Task Parameter for SMS Number + string + user + global + SMS Recipient Number + + Task Parameter for SMS Number + +
Entity Label @@ -2330,6 +2426,55 @@ Change log file after synchronization
+
+ + Entity Label + string + developer + global + DUNE Resources Monitor + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 0 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + +
Entity Label @@ -2848,7 +2993,7 @@ list:string developer global - EstimatedState:Navigation Manager, Temperature:CTD, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager + VerticalProfile:CTD, VerticalProfile:ADCP List of messages <Message>:<Entity> to send using Iridium. @@ -3708,6 +3853,15 @@ Power Channel Entity Label + + Power Channel 1 Max Current + integer + developer + global + 5001 + + Power Channel Max Current + Power Channel 2 Entity Label string @@ -3717,6 +3871,15 @@ Power Channel Entity Label + + Power Channel 2 Max Current + integer + developer + global + 5002 + + Power Channel Max Current + Power Channel 3 Entity Label string @@ -3735,6 +3898,15 @@ Power Channel State + + Power Channel 3 Max Current + integer + developer + global + 5003 + + Power Channel Max Current + Power Channel 4 Entity Label string @@ -3753,6 +3925,15 @@ Power Channel State + + Power Channel 4 Max Current + integer + developer + global + 5004 + + Power Channel Max Current + Power Channel 5 Entity Label string @@ -3771,6 +3952,15 @@ Power Channel State + + Power Channel 5 Max Current + integer + developer + global + 5005 + + Power Channel Max Current + Power Channel 6 Entity Label string @@ -3789,6 +3979,15 @@ Power Channel State + + Power Channel 6 Max Current + integer + developer + global + 5006 + + Power Channel Max Current + Power Channel 7 Entity Label string @@ -3807,6 +4006,15 @@ Power Channel State + + Power Channel 7 Max Current + integer + developer + global + 5007 + + Power Channel Max Current + Power Channel 8 Entity Label string @@ -3825,6 +4033,15 @@ Power Channel State + + Power Channel 8 Max Current + integer + developer + global + 5008 + + Power Channel Max Current + Power Channel 9 Entity Label string @@ -3843,6 +4060,15 @@ Power Channel State + + Power Channel 9 Max Current + integer + developer + global + 5009 + + Power Channel Max Current + Power Channel 10 Entity Label string @@ -3861,6 +4087,15 @@ Power Channel State + + Power Channel 10 Max Current + integer + developer + global + 5010 + + Power Channel Max Current + Power Channel 11 Entity Label string @@ -3879,6 +4114,15 @@ Power Channel State + + Power Channel 11 Max Current + integer + developer + global + 5011 + + Power Channel Max Current + Power Channel 12 Entity Label string @@ -3897,6 +4141,15 @@ Power Channel State + + Power Channel 12 Max Current + integer + developer + global + 5012 + + Power Channel Max Current + Power Channel 13 Entity Label string @@ -3915,12 +4168,21 @@ Power Channel State + + Power Channel 13 Max Current + integer + developer + global + 5013 + + Power Channel Max Current + Power Channel 14 Entity Label string developer global - LED + Private (FLED) Power Channel Entity Label @@ -3933,6 +4195,15 @@ Power Channel State + + Power Channel 14 Max Current + integer + developer + global + 5014 + + Power Channel Max Current + Power Channel 15 Entity Label string @@ -3951,6 +4222,15 @@ Power Channel State + + Power Channel 15 Max Current + integer + developer + global + 5015 + + Power Channel Max Current + Power Channel 16 Entity Label string @@ -3969,6 +4249,15 @@ Power Channel State + + Power Channel 16 Max Current + integer + developer + global + 5016 + + Power Channel Max Current + Power Channel 17 Entity Label string @@ -3987,6 +4276,15 @@ Power Channel State + + Power Channel 17 Max Current + integer + developer + global + 5017 + + Power Channel Max Current + Power Channel 18 Entity Label string @@ -4005,6 +4303,15 @@ Power Channel State + + Power Channel 18 Max Current + integer + developer + global + 5018 + + Power Channel Max Current + Power Data 1 Entity Label string @@ -4194,6 +4501,42 @@ Set CPC to use NAV and Iridium at Boot. + + Force Water Mode at Boot + boolean + developer + global + false + + Force Water Mode at Boot. + + + Use Software Fuse + boolean + developer + global + false + + CPC Use Software Fuse. + + + Timeout Transmission Request + integer + developer + global + 120 + + Timeout, in seconds, for TransmissionRequest + + + Default SMS Recipient Number + string + user + global + + + Phone number of the SMS recipient +
@@ -4582,7 +4925,7 @@ string developer global - maneuver + global Scoped of the 'Active' parameter @@ -4591,15 +4934,15 @@ string developer global - user + developer Visibility of the 'Active' parameter Active boolean - user - maneuver + developer + global 1 True to activate task, false otherwise @@ -4695,23 +5038,32 @@ Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - Sampling Duration - real + + Start Acquisition + boolean user maneuver - 0.0 + false - Sampling duration in seconds + Start Acquisition. - - Sampling Period - real - user + + Sample Time Duration + integer + user maneuver - 0.0 - - Sampling period in seconds + 60 + s + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + s + Periodicity of Data Sampling in seconds. Timeout Transmitting Iridium Message @@ -6405,7 +6757,7 @@ string developer global - GSM + SMS Entity label of GSM modem @@ -6665,145 +7017,6 @@ Maximum amount of seconds to wait for missing fragments in incoming messages
-
- - Entity Label - string - developer - global - GSM - - Main entity label - - - Execution Priority - integer - developer - global - 10 - - Execution priority - - - Activation Time - integer - developer - global - 10 - - - - - Deactivation Time - integer - developer - global - 0 - - - - - Debug Level - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Serial Port - Device - string - developer - global - /dev/ttyUSB3 - - Serial port device used to communicate with the sensor - - - Serial Port - Baud Rate - integer - developer - global - 115200 - - Serial port baud rate - - - Reply Timeout - real - developer - global - 2.0 - s - Amount of time to wait for a command reply - - - PIN - string - developer - global - - - PIN Code - - - RSSI Periodicity - real - developer - global - 10 - s - Periodicity of RSSI reports - - - Read SMS Periodicity - real - developer - global - 10 - s - Periodicity of received SMS checks - - - SMS Send Timeout - real - developer - global - 60 - s - Maximum amount of time to wait for SMS send completion - - - USSD code - integer - developer - global - 111 - - USSD code - - - Request Balance - boolean - user - global - false - - Enable Balance Request - - - Balance Periodicity - integer - developer - global - 60 - - Balance Periodicity - -
Entity Label @@ -6866,7 +7079,7 @@ integer developer global - 5 + 10 Number of worker threads @@ -6875,7 +7088,16 @@ list:string developer global - CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage, AirSaturation, Chlorophyll, Conductivity, Pressure, Salinity, Turbidity, WindSpeed + Announce, CpuUsage, Current, Distance, EntityState, EntityInfo, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, VehicleState, Voltage, AirSaturation, Chlorophyll, Conductivity, Pressure, Salinity, Turbidity, WindSpeed + + List of messages to transport + + + Number Lines From LogBook to send + integer + developer + global + 500 List of messages to transport @@ -7289,6 +7511,26 @@ Window to prioritize Reception over Transmission 5 + + Maximum Errors + integer + developer + global + 3 + + Maximum number of errors to trigger restart + 0 + + + Error Reset Period + real + developer + global + 300 + + Period to reset error count + 60 +
@@ -7433,6 +7675,145 @@
+
+ + Entity Label + string + developer + global + SMS + + Main entity label + + + Execution Priority + integer + developer + global + 10 + + Execution priority + + + Activation Time + integer + developer + global + 10 + + + + + Deactivation Time + integer + developer + global + 0 + + + + + Debug Level + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Serial Port - Device + string + developer + global + /dev/ttyUSB3 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 115200 + + Serial port baud rate + + + Reply Timeout + real + developer + global + 2.0 + s + Amount of time to wait for a command reply + + + PIN + string + developer + global + + + PIN Code + + + RSSI Periodicity + real + developer + global + 10 + s + Periodicity of RSSI reports + + + Read SMS Periodicity + real + developer + global + 10 + s + Periodicity of received SMS checks + + + SMS Send Timeout + real + developer + global + 60 + s + Maximum amount of time to wait for SMS send completion + + + USSD code + integer + developer + global + 111 + + USSD code + + + Request Balance + boolean + user + global + false + + Enable Balance Request + + + Balance Periodicity + integer + developer + global + 60 + + Balance Periodicity + +
Entity Label diff --git a/conf/params/caravel.pt_PT.xml b/conf/params/caravel.pt_PT.xml index 92f3c6cec2..a796079900 100644 --- a/conf/params/caravel.pt_PT.xml +++ b/conf/params/caravel.pt_PT.xml @@ -1,5 +1,5 @@ - +
Nome da Entidade @@ -2108,6 +2108,102 @@ None, Debug, Trace, Spew
+
+ + Nome da Entidade + string + developer + global + Boot Monitor + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Boot Message Delay + real + developer + global + 10 + + Delay, in seconds, before dispatching boot message. Value can not be less than 1s. + 1 + + + Boot Message TTL + real + developer + global + 300 + + Boot message time-to-live, in seconds. Value can not be less than 60s. + 60 + + + Default SMS Recipient Number + string + user + global + + + Número de telefone do destinatário de mensagens SMS + + + Task Label for SMS Number + string + user + global + Monitors.Emergency + + Task Label for SMS Number + + + Task Parameter for SMS Number + string + user + global + SMS Recipient Number + + Task Parameter for SMS Number + +
Nome da Entidade @@ -2330,6 +2426,55 @@ Change log file after synchronization
+
+ + Nome da Entidade + string + developer + global + DUNE Resources Monitor + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 0 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + +
Nome da Entidade @@ -2848,7 +2993,7 @@ list:string developer global - EstimatedState:Navigation Manager, Temperature:CTD, Salinity:CTD, CurrentProfile:ADCP, EstimatedState:Simulated Navigation Manager + VerticalProfile:CTD, VerticalProfile:ADCP List of messages <Message>:<Entity> to send using Iridium. @@ -3708,6 +3853,15 @@ Power Channel Entity Label + + Power Channel 1 Max Current + integer + developer + global + 5001 + + Power Channel Max Current + Power Channel 2 Entity Label string @@ -3717,6 +3871,15 @@ Power Channel Entity Label + + Power Channel 2 Max Current + integer + developer + global + 5002 + + Power Channel Max Current + Power Channel 3 Entity Label string @@ -3735,6 +3898,15 @@ Power Channel State + + Power Channel 3 Max Current + integer + developer + global + 5003 + + Power Channel Max Current + Power Channel 4 Entity Label string @@ -3753,6 +3925,15 @@ Power Channel State + + Power Channel 4 Max Current + integer + developer + global + 5004 + + Power Channel Max Current + Power Channel 5 Entity Label string @@ -3771,6 +3952,15 @@ Power Channel State + + Power Channel 5 Max Current + integer + developer + global + 5005 + + Power Channel Max Current + Power Channel 6 Entity Label string @@ -3789,6 +3979,15 @@ Power Channel State + + Power Channel 6 Max Current + integer + developer + global + 5006 + + Power Channel Max Current + Power Channel 7 Entity Label string @@ -3807,6 +4006,15 @@ Power Channel State + + Power Channel 7 Max Current + integer + developer + global + 5007 + + Power Channel Max Current + Power Channel 8 Entity Label string @@ -3825,6 +4033,15 @@ Power Channel State + + Power Channel 8 Max Current + integer + developer + global + 5008 + + Power Channel Max Current + Power Channel 9 Entity Label string @@ -3843,6 +4060,15 @@ Power Channel State + + Power Channel 9 Max Current + integer + developer + global + 5009 + + Power Channel Max Current + Power Channel 10 Entity Label string @@ -3861,6 +4087,15 @@ Power Channel State + + Power Channel 10 Max Current + integer + developer + global + 5010 + + Power Channel Max Current + Power Channel 11 Entity Label string @@ -3879,6 +4114,15 @@ Power Channel State + + Power Channel 11 Max Current + integer + developer + global + 5011 + + Power Channel Max Current + Power Channel 12 Entity Label string @@ -3897,6 +4141,15 @@ Power Channel State + + Power Channel 12 Max Current + integer + developer + global + 5012 + + Power Channel Max Current + Power Channel 13 Entity Label string @@ -3915,12 +4168,21 @@ Power Channel State + + Power Channel 13 Max Current + integer + developer + global + 5013 + + Power Channel Max Current + Power Channel 14 Entity Label string developer global - LED + Private (FLED) Power Channel Entity Label @@ -3933,6 +4195,15 @@ Power Channel State + + Power Channel 14 Max Current + integer + developer + global + 5014 + + Power Channel Max Current + Power Channel 15 Entity Label string @@ -3951,6 +4222,15 @@ Power Channel State + + Power Channel 15 Max Current + integer + developer + global + 5015 + + Power Channel Max Current + Power Channel 16 Entity Label string @@ -3969,6 +4249,15 @@ Power Channel State + + Power Channel 16 Max Current + integer + developer + global + 5016 + + Power Channel Max Current + Power Channel 17 Entity Label string @@ -3987,6 +4276,15 @@ Power Channel State + + Power Channel 17 Max Current + integer + developer + global + 5017 + + Power Channel Max Current + Power Channel 18 Entity Label string @@ -4005,6 +4303,15 @@ Power Channel State + + Power Channel 18 Max Current + integer + developer + global + 5018 + + Power Channel Max Current + Power Data 1 Entity Label string @@ -4194,6 +4501,42 @@ Set CPC to use NAV and Iridium at Boot. + + Force Water Mode at Boot + boolean + developer + global + false + + Force Water Mode at Boot. + + + Use Software Fuse + boolean + developer + global + false + + CPC Use Software Fuse. + + + Timeout Transmission Request + integer + developer + global + 120 + + Timeout, in seconds, for TransmissionRequest + + + Default SMS Recipient Number + string + user + global + + + Número de telefone do destinatário de mensagens SMS +
@@ -4582,7 +4925,7 @@ string developer global - maneuver + global Escopo do parâmetro 'Ativa' @@ -4591,15 +4934,15 @@ string developer global - user + developer Visibilidade do parâmetro 'Ativa' Ativa boolean - user - maneuver + developer + global 1 Verdadeiro para ativar tarefa, falso caso contrário @@ -4695,23 +5038,32 @@ Scale factor is used to derive instrument output concentration from the raw signal output of the fluorometer - - Sampling Duration - real + + Start Acquisition + boolean user maneuver - 0.0 + false - Sampling duration in seconds + Start Acquisition. - - Sampling Period - real - user + + Sample Time Duration + integer + user maneuver - 0.0 - - Sampling period in seconds + 60 + s + Sample Time Duration in seconds. + + + Periodicity of Data Sampling + integer + user + maneuver + 80 + s + Periodicity of Data Sampling in seconds. Timeout Transmitting Iridium Message @@ -6405,7 +6757,7 @@ string developer global - GSM + SMS Entity label of GSM modem @@ -6665,145 +7017,6 @@ Maximum amount of seconds to wait for missing fragments in incoming messages
-
- - Nome da Entidade - string - developer - global - GSM - - Nome principal da entidade - - - Prioridade de Execução - integer - developer - global - 10 - - Prioridade de execução - - - Tempo de Ativação - integer - developer - global - 10 - - - - - Tempo de Desativação - integer - developer - global - 0 - - - - - Nível de Depuração - string - developer - global - None - - - None, Debug, Trace, Spew - None, Debug, Trace, Spew - - - Serial Port - Device - string - developer - global - /dev/ttyUSB3 - - Serial port device used to communicate with the sensor - - - Serial Port - Baud Rate - integer - developer - global - 115200 - - Serial port baud rate - - - Reply Timeout - real - developer - global - 2.0 - s - Amount of time to wait for a command reply - - - PIN - string - developer - global - - - PIN Code - - - RSSI Periodicity - real - developer - global - 10 - s - Periodicity of RSSI reports - - - Read SMS Periodicity - real - developer - global - 10 - s - Periodicity of received SMS checks - - - SMS Send Timeout - real - developer - global - 60 - s - Maximum amount of time to wait for SMS send completion - - - USSD code - integer - developer - global - 111 - - USSD code - - - Request Balance - boolean - user - global - false - - Enable Balance Request - - - Balance Periodicity - integer - developer - global - 60 - - Balance Periodicity - -
Nome da Entidade @@ -6866,7 +7079,7 @@ integer developer global - 5 + 10 Number of worker threads @@ -6875,7 +7088,16 @@ list:string developer global - CpuUsage, Current, Distance, EntityState, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, Voltage, AirSaturation, Chlorophyll, Conductivity, Pressure, Salinity, Turbidity, WindSpeed + Announce, CpuUsage, Current, Distance, EntityState, EntityInfo, FuelLevel, GpsFix, Heartbeat, PowerChannelState, RSSI, Rpm, StorageUsage, Temperature, VehicleState, Voltage, AirSaturation, Chlorophyll, Conductivity, Pressure, Salinity, Turbidity, WindSpeed + + List of messages to transport + + + Number Lines From LogBook to send + integer + developer + global + 500 List of messages to transport @@ -7289,6 +7511,26 @@ Window to prioritize Reception over Transmission 5 + + Maximum Errors + integer + developer + global + 3 + + Maximum number of errors to trigger restart + 0 + + + Error Reset Period + real + developer + global + 300 + + Period to reset error count + 60 +
@@ -7433,6 +7675,145 @@
+
+ + Nome da Entidade + string + developer + global + SMS + + Nome principal da entidade + + + Prioridade de Execução + integer + developer + global + 10 + + Prioridade de execução + + + Tempo de Ativação + integer + developer + global + 10 + + + + + Tempo de Desativação + integer + developer + global + 0 + + + + + Nível de Depuração + string + developer + global + None + + + None, Debug, Trace, Spew + None, Debug, Trace, Spew + + + Serial Port - Device + string + developer + global + /dev/ttyUSB3 + + Serial port device used to communicate with the sensor + + + Serial Port - Baud Rate + integer + developer + global + 115200 + + Serial port baud rate + + + Reply Timeout + real + developer + global + 2.0 + s + Amount of time to wait for a command reply + + + PIN + string + developer + global + + + PIN Code + + + RSSI Periodicity + real + developer + global + 10 + s + Periodicity of RSSI reports + + + Read SMS Periodicity + real + developer + global + 10 + s + Periodicity of received SMS checks + + + SMS Send Timeout + real + developer + global + 60 + s + Maximum amount of time to wait for SMS send completion + + + USSD code + integer + developer + global + 111 + + USSD code + + + Request Balance + boolean + user + global + false + + Enable Balance Request + + + Balance Periodicity + integer + developer + global + 60 + + Balance Periodicity + +
Nome da Entidade From a99afa6c351f2f14b09c968f583c9a22feef442b Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 18 Nov 2024 13:43:56 +0000 Subject: [PATCH 57/92] console/ConsolePanel: Change sendViaIridium to return if there was an error sending through Iridium (success is not guaranteed in some cases). --- src/java/pt/lsts/neptus/console/ConsolePanel.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/java/pt/lsts/neptus/console/ConsolePanel.java b/src/java/pt/lsts/neptus/console/ConsolePanel.java index 5f236f020d..a64a5b63b8 100644 --- a/src/java/pt/lsts/neptus/console/ConsolePanel.java +++ b/src/java/pt/lsts/neptus/console/ConsolePanel.java @@ -832,7 +832,7 @@ public boolean send(IMCMessage message) { return send(destination, message); } - public void sendViaIridium(String destination, IMCMessage message) { + public boolean sendViaIridium(String destination, IMCMessage message) { if (message.getTimestamp() == 0) message.setTimestampMillis(System.currentTimeMillis()); Collection irMsgs = new ArrayList(); @@ -841,7 +841,7 @@ public void sendViaIridium(String destination, IMCMessage message) { } catch (Exception e) { GuiUtils.errorMessage(getConsole(), "Send by Iridium", e.getMessage()); - return; + return false; } int src = getConsole().getImcMsgManager().getLocalId().intValue(); int dst = IMCDefinition.getInstance().getResolver().resolve(destination); @@ -860,10 +860,11 @@ public void sendViaIridium(String destination, IMCMessage message) { getConsole().post(Notification.success("Iridium message sent", count + " Iridium messages were sent using " + IridiumManager.getManager().getCurrentMessenger().getName())); + return true; } catch (Exception e) { GuiUtils.errorMessage(getConsole(), "Send by Iridium", e.getMessage()); - return; + return false; } } From e9dc267ab68f1220633e01002e21a36980d07816 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 18 Nov 2024 13:44:50 +0000 Subject: [PATCH 58/92] plugins/oplimits/OperationLimitsSubPanel: Protecting from freezing the gui. --- .../oplimits/OperationLimitsSubPanel.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/plugins-dev/oplimits/src/java/pt/lsts/neptus/plugins/oplimits/OperationLimitsSubPanel.java b/plugins-dev/oplimits/src/java/pt/lsts/neptus/plugins/oplimits/OperationLimitsSubPanel.java index 3727d9cd11..0b3c1620e8 100644 --- a/plugins-dev/oplimits/src/java/pt/lsts/neptus/plugins/oplimits/OperationLimitsSubPanel.java +++ b/plugins-dev/oplimits/src/java/pt/lsts/neptus/plugins/oplimits/OperationLimitsSubPanel.java @@ -69,6 +69,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import javax.swing.SwingWorker; import javax.swing.border.EmptyBorder; import com.google.common.eventbus.Subscribe; @@ -251,10 +252,17 @@ public void actionPerformed(ActionEvent e) { synchronized (OperationLimitsSubPanel.this) { lastMD5 = msg.payloadMD5(); - boolean ret = send(msg); - if (ret) { - send(new GetOperationalLimits()); - } + SwingWorker worker = new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + boolean ret = send(msg); + if (ret) { + send(new GetOperationalLimits()); + } + return ret; + } + }; + worker.execute(); } } }; @@ -273,7 +281,13 @@ public void actionPerformed(ActionEvent e) { updateAction.putValue(AbstractAction.SMALL_ICON, ICON_UPDATE_REQUEST); } updateAction.putValue(AbstractAction.SHORT_DESCRIPTION, TEXT_REQUEST_RESPONSE_WAITING); - send(IMCDefinition.getInstance().create("GetOperationalLimits")); + SwingWorker worker = new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + return send(IMCDefinition.getInstance().create("GetOperationalLimits")); + } + }; + worker.execute(); } }; @@ -365,8 +379,7 @@ public boolean send(IMCMessage message) { if (userAproveRequest) { lastRequest = new Date(); } - sendViaIridium(destination, message); - return true; + return sendViaIridium(destination, message); } else { return false; } From 46bc14062292d8c78692555ed023f505b30e4bac Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 18 Nov 2024 14:17:35 +0000 Subject: [PATCH 59/92] console/plugins/planning/MissionTreePanel: Protecting from freezing the gui. --- .../plugins/planning/MissionTreePanel.java | 140 +++++++++++++----- 1 file changed, 101 insertions(+), 39 deletions(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java index 6661ea106b..3c2e97e4fe 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java @@ -206,8 +206,16 @@ private void addClearPlanDbMenuItem() { PluginUtils.getPluginIcon(getClass())), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (pdbControl != null) - pdbControl.clearDatabase(); + if (pdbControl != null) { + SwingWorker sw = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + pdbControl.clearDatabase(); + return null; + } + }; + sw.execute(); + } } }); } @@ -438,22 +446,28 @@ private void addActionSendPlan(final ConsoleLayout console2, final PlanDBControl final ArrayList selectedItems, JPopupMenu popupMenu) { if (!usePlanDBSyncFeatures) return; - + popupMenu.add( I18n.textf("Send %planName to %system", getPlanNamesString(selectedItems, true), console2.getMainSystem())) - .addActionListener( - - new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - for (NameId nameId : selectedItems) { - PlanType sel = (PlanType) nameId; - String mainSystem = console2.getMainSystem(); - pdbControl.setRemoteSystemId(mainSystem); - pdbControl.sendPlan(sel); - } - } - }); + .addActionListener(e -> { + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + for (NameId nameId : selectedItems) { + PlanType sel = (PlanType) nameId; + String mainSystem = console2.getMainSystem(); + pdbControl.setRemoteSystemId(mainSystem); + boolean ret = pdbControl.sendPlan(sel); + if (!ret) { + NeptusLog.pub().error("Error sending plan " + sel.getId()); + break; + } + } + return null; + } + }; + worker.execute(); + }); } private void addActionSendPlanInfoRequest(final ConsoleLayout console2, final PlanDBControl pdbControl, @@ -463,12 +477,23 @@ private void addActionSendPlanInfoRequest(final ConsoleLayout console2, final Pl popupMenu.add(I18n.textf("Get %planName info from %system", getPlanNamesString(selectedItems, true), console2.getMainSystem())) .addActionListener(e -> { - for (NameId nameId : selectedItems) { - PlanType sel = (PlanType) nameId; - String mainSystem = console2.getMainSystem(); - pdbControl.setRemoteSystemId(mainSystem); - pdbControl.requestPlanInfo(sel.getId()); - } + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + for (NameId nameId : selectedItems) { + PlanType sel = (PlanType) nameId; + String mainSystem = console2.getMainSystem(); + pdbControl.setRemoteSystemId(mainSystem); + boolean ret = pdbControl.requestPlanInfo(sel.getId()); + if (!ret) { + NeptusLog.pub().error("Error requesting plan info " + sel.getId()); + break; + } + } + return null; + } + }; + worker.execute(); }); } @@ -535,9 +560,21 @@ private void addActionGetRemotePlan(final ConsoleLayout console2, final PlanDBCo .addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - for (NameId nameId : remotePlans) { - pdbControl.requestPlan(nameId.getIdentification()); - } + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + pdbControl.setRemoteSystemId(console2.getMainSystem()); + for (NameId nameId : remotePlans) { + boolean ret = pdbControl.requestPlan(nameId.getIdentification()); + if (!ret) { + NeptusLog.pub().error("Error requesting plan " + nameId.getIdentification()); + break; + } + } + return null; + } + }; + worker.execute(); } }); } @@ -557,7 +594,14 @@ public void actionPerformed(ActionEvent e) { // Request LBLConfig LblConfig msgLBLConfiguration = new LblConfig(); msgLBLConfiguration.setOp(LblConfig.OP.GET_CFG); - sendMsg(msgLBLConfiguration); + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + sendMsg(msgLBLConfiguration); + return null; + } + }; + worker.execute(); } }); } @@ -572,10 +616,21 @@ private void addActionRemovePlanRemotely(final ConsoleLayout console2, final Pla console2.getMainSystem())).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - pdbControl.setRemoteSystemId(console2.getMainSystem()); - for (NameId nameId : synAndUnsyncPlans) { - pdbControl.deletePlan(nameId.getIdentification()); - } + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + pdbControl.setRemoteSystemId(console2.getMainSystem()); + for (NameId nameId : synAndUnsyncPlans) { + boolean ret = pdbControl.deletePlan(nameId.getIdentification()); + if (!ret) { + NeptusLog.pub().error("Error deleting plan " + nameId.getIdentification()); + break; + } + } + return null; + } + }; + worker.execute(); } }); } @@ -807,15 +862,22 @@ private void addActionRemoveAllTrans(JPopupMenu popupMenu) { popupMenu.add(I18n.text("Remove all transponders from vehicle")).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - LblConfig msgLBLConfiguration = new LblConfig(); - msgLBLConfiguration.setOp(LblConfig.OP.SET_CFG); - msgLBLConfiguration.setBeacons(new Vector()); - sendMsg(msgLBLConfiguration); - msgLBLConfiguration = new LblConfig(); - msgLBLConfiguration.setOp(LblConfig.OP.GET_CFG); - sendMsg(msgLBLConfiguration); - // TODO On hold until removing all beacons is stable - // browser.removeAllTransponders(console.getMission()); + SwingWorker sw = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + LblConfig msgLBLConfiguration = new LblConfig(); + msgLBLConfiguration.setOp(LblConfig.OP.SET_CFG); + msgLBLConfiguration.setBeacons(new Vector()); + sendMsg(msgLBLConfiguration); + msgLBLConfiguration = new LblConfig(); + msgLBLConfiguration.setOp(LblConfig.OP.GET_CFG); + sendMsg(msgLBLConfiguration); + // TODO On hold until removing all beacons is stable + // browser.removeAllTransponders(console.getMission()); + return null; + } + }; + sw.execute(); } }); } From d1fe4d2e6d5328e53649d1b8c95a0ad8450b0b1a Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 18 Nov 2024 14:18:24 +0000 Subject: [PATCH 60/92] console/plugins/planning/MissionTreePanel: To fix - marking possible wrong info to user. --- .../lsts/neptus/console/plugins/planning/MissionTreePanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java index 3c2e97e4fe..ee72e789ec 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java @@ -584,7 +584,7 @@ private void addActionGetRemoteTrans(final ConsoleLayout console2, JPopupMenu po if (!useTransponderFeatures) return; - StringBuilder itemsInString = getPlanNamesString(remoteTrans, false); + StringBuilder itemsInString = getPlanNamesString(remoteTrans, false); // Check info text, seams wrong, it is a transponder popupMenu.add(I18n.textf("Get %planName from %system", itemsInString, console2.getMainSystem())) .addActionListener(new ActionListener() { @Override From 454e530bfbdc4a2cb171ad3f4875b1463ba8b265 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 19 Nov 2024 17:14:18 +0000 Subject: [PATCH 61/92] params/SystemConfigurationEditorPanel: Start collapse and keep open state switching back and forward from advanced. --- .../SystemConfigurationEditorPanel.java | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index fe5e3b6539..c41064f4c9 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -42,6 +42,7 @@ import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -316,7 +317,7 @@ public void setRefreshing(boolean refreshing) { private synchronized void refreshPropertiesOnPanel() { titleLabel.setText("" + createTitle() + ""); - removeAllPropertiesFromPanel(); + List openCategories = removeAllPropertiesFromPanel(); resetPropertiesEditorAndRendererFactories(); @@ -347,7 +348,16 @@ private synchronized void refreshPropertiesOnPanel() { for (String sectionName : secNames) { queryValues(sectionName, scopeToUse.getText(), visibility.getText()); } - + + for (int i = 0; i < psp.getTable().getSheetModel().getRowCount(); i++) { + Item o = (Item) psp.getTable().getSheetModel().getObject(i); + if (o.isVisible() && !o.hasToggle()) { + if (!openCategories.contains(o.getParent().getName())) { + o.getParent().toggle(); + } + } + } + revalidate(); repaint(); } @@ -359,11 +369,24 @@ private synchronized void resetPropertiesOnPanel() { psp.repaint(); } - private void removeAllPropertiesFromPanel() { + private List removeAllPropertiesFromPanel() { + List toggledCategories = new ArrayList<>(); + for (int i = 0; i < psp.getTable().getSheetModel().getRowCount(); i++) { + Item o = (Item) psp.getTable().getSheetModel().getObject(i); + if (o.isVisible() && !o.hasToggle()) { + String name = o.getParent().getName(); + if (!toggledCategories.contains(name)) { + toggledCategories.add(name); + } + } + } + params.clear(); for (Property p : psp.getProperties()) { psp.removeProperty(p); } + + return toggledCategories; } private String createTitle() { From 9501854ccad96bb53d68d0113a2138cc075641d6 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 21 Nov 2024 13:46:03 +0000 Subject: [PATCH 62/92] params/SystemConfigurationEditorPanel: Adding expand all elements button. --- .../SystemConfigurationEditorPanel.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index c41064f4c9..f55c424520 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -95,7 +95,8 @@ public class SystemConfigurationEditorPanel extends JPanel implements PropertyCh private JButton refreshButton; private JButton resetButton; private JButton collapseButton; - + private JButton expandButton; + private JLabel titleLabel; private JCheckBox checkAdvance; private JComboBox scopeComboBox; @@ -222,8 +223,25 @@ public void actionPerformed(ActionEvent e) { } }); collapseButton.setToolTipText(I18n.text("Collapse all sections.")); - add(collapseButton, "sg buttons, split"); + add(collapseButton, "sg buttons"); + expandButton = new JButton(new AbstractAction(I18n.text("Expand All")) { + @Override + public void actionPerformed(ActionEvent e) { + for (int i = 0; i < psp.getTable().getSheetModel().getRowCount(); i++) { + Item o = (Item) psp.getTable().getSheetModel().getObject(i); + if (!o.isVisible()) { + if (o.hasToggle() && !o.isVisible()) { + o.toggle(); + } else if (!o.hasToggle() && o.getParent() != null && !o.getParent().isVisible()) { + o.getParent().toggle(); + } + } + } + } + }); + expandButton.setToolTipText(I18n.text("Expand all sections.")); + add(expandButton, "sg buttons, split"); resetButton = new JButton(new AbstractAction(I18n.text("Reset")) { @Override From 896dbddce83aaabe4719d1eba25049e8f5babf43 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 22 Nov 2024 17:06:05 +0000 Subject: [PATCH 63/92] params/SystemConfigurationEditorPanel: First version to choose from parameters to request or send. --- .../SystemConfigurationEditorPanel.java | 245 ++++++++++++++++-- 1 file changed, 229 insertions(+), 16 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index f55c424520..5c8bda40d0 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -32,28 +32,43 @@ */ package pt.lsts.neptus.params; +import java.awt.CardLayout; import java.awt.Component; +import java.awt.Dialog; +import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; +import java.util.stream.Collectors; import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.KeyStroke; import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; import com.l2fprod.common.propertysheet.Property; import com.l2fprod.common.propertysheet.PropertyEditorRegistry; @@ -87,9 +102,15 @@ @SuppressWarnings("serial") public class SystemConfigurationEditorPanel extends JPanel implements PropertyChangeListener { + public static final String CARD_PROPERTIES = "properties"; + public static final String CARD_CATEGORIES = "categories"; protected final LinkedHashMap params = new LinkedHashMap<>(); + private static boolean isAskForCategories = false; + protected PropertySheetPanel psp; + private JPanel categoriesPanel; + private JPanel swapPropertiesAndCategoriesPanel; private JButton sendButton; private JButton saveButton; private JButton refreshButton; @@ -99,6 +120,7 @@ public class SystemConfigurationEditorPanel extends JPanel implements PropertyCh private JLabel titleLabel; private JCheckBox checkAdvance; + private JCheckBox checkSelection; private JComboBox scopeComboBox; protected boolean refreshing = false; @@ -177,8 +199,14 @@ public void run() { psp.setToolBarVisible(false); resetPropertiesEditorAndRendererFactories(); - - add(psp, "w 100%, h 100%, wrap"); + + categoriesPanel = new JPanel(new MigLayout("fill, insets 0")); + + swapPropertiesAndCategoriesPanel = new JPanel(new CardLayout()); + swapPropertiesAndCategoriesPanel.add(psp, CARD_PROPERTIES); + //swapPropertiesAndCategoriesPanel.add(categoriesPanel, CARD_CATEGORIES); + + add(swapPropertiesAndCategoriesPanel, "w 100%, h 100%, wrap"); sendButton = new JButton(new AbstractAction(I18n.text("Send")) { @Override @@ -194,7 +222,7 @@ public void actionPerformed(ActionEvent e) { refreshButton = new JButton(new AbstractAction(I18n.text("Refresh")) { @Override public void actionPerformed(ActionEvent e) { - refreshPropertiesOnPanel(); + refreshPropertiesOnPanel(true); } }); refreshButton.setToolTipText(I18n.text("Requests the entities sections parameters from the vehicle.")); @@ -260,10 +288,7 @@ public void actionPerformed(ActionEvent e) { checkAdvance = new JCheckBox(I18n.text("Access Developer Parameters")); checkAdvance.setToolTipText("" + I18n.textc("Be careful changing these values.
They may make the vehicle inoperable.", "This will be a tooltip, and use
to change line.")); -// if (ConfigFetch.getDistributionType() == DistributionEnum.DEVELOPER) - add(checkAdvance); -// else -// visibility = Visibility.USER; + add(checkAdvance, "split, sg checkboxes"); if (visibility == Visibility.DEVELOPER) checkAdvance.setSelected(true); else @@ -276,17 +301,47 @@ public void itemStateChanged(ItemEvent e) { else visibility = Visibility.USER; - refreshPropertiesOnPanel(); + // FIXME This might not make sense to not always ask for categories + refreshPropertiesOnPanel(true); } }); checkAdvance.setFocusable(false); - refreshPropertiesOnPanel(); + checkSelection = new JCheckBox(I18n.text("Ask for categories")); + checkSelection.setToolTipText("" + I18n.textc("Ask for categories before send.", + "This will be a tooltip, and use
to change line.")); + checkSelection.addItemListener(e -> { + isAskForCategories = checkSelection.isSelected(); + updateSendButtons(); + }); + checkSelection.setSelected(isAskForCategories); + checkSelection.setFocusable(false); + add(checkSelection, "sg checkboxes"); + + refreshPropertiesOnPanel(false); revalidate(); repaint(); } + private void updateSendButtons() { + List actions = new ArrayList<>(); + actions.add(sendButton.getAction()); + actions.add(refreshButton.getAction()); + actions.add(saveButton.getAction()); + + String suffix = " #"; + for (Action action : actions) { + String name = (String) action.getValue("Name"); + if (!isAskForCategories && name.endsWith(suffix)) { + name = name.substring(0, name.length() - 2); + } else if (isAskForCategories && !name.endsWith(suffix)) { + name += suffix; + } + action.putValue("Name", name); + } + } + private void resetPropertiesEditorAndRendererFactories() { per = new PropertyEditorRegistry(); // per.registerDefaults(); @@ -316,7 +371,8 @@ public String getSystemId() { public void setSystemId(String systemId) { this.systemId = systemId; sid = ImcSystemsHolder.getSystemWithName(this.systemId); - refreshPropertiesOnPanel(); + // FIXME This might not make sense to not always ask for categories + refreshPropertiesOnPanel(true); } /** @@ -333,7 +389,10 @@ public void setRefreshing(boolean refreshing) { this.refreshing = refreshing; } - private synchronized void refreshPropertiesOnPanel() { + private synchronized void refreshPropertiesOnPanel(boolean askForCategories) { + // FIXME + Map oldCategoriesOnPanel = getCategoriesOnPanel(true); + titleLabel.setText("" + createTitle() + ""); List openCategories = removeAllPropertiesFromPanel(); @@ -363,10 +422,8 @@ private synchronized void refreshPropertiesOnPanel() { sp.propertyChange(evt); } } - for (String sectionName : secNames) { - queryValues(sectionName, scopeToUse.getText(), visibility.getText()); - } + // Close all categories for (int i = 0; i < psp.getTable().getSheetModel().getRowCount(); i++) { Item o = (Item) psp.getTable().getSheetModel().getObject(i); if (o.isVisible() && !o.hasToggle()) { @@ -376,6 +433,28 @@ private synchronized void refreshPropertiesOnPanel() { } } + List queryCategoriesList; + if (askForCategories && isAskForCategories) { + List validCategories; + try { + validCategories = askForCategories(oldCategoriesOnPanel).get(); + } + catch (Exception e) { + // Do nothing + validCategories = Collections.emptyList(); + } + queryCategoriesList = new ArrayList<>(); + for (String category : validCategories) { + if (category != null && validCategories.contains(category)) + queryCategoriesList.add(category); + } + } else { + queryCategoriesList = secNames; + } + for (String sectionName : queryCategoriesList) { + queryValues(sectionName, scopeToUse.getText(), visibility.getText()); + } + revalidate(); repaint(); } @@ -484,14 +563,139 @@ private void sendProperty(SystemProperty... propsList) { } } + private Map getCategoriesOnPanel(boolean onlyVisible) { + Map categories = new LinkedHashMap<>(); + for (SystemProperty sp : params.values()) { + String category = sp.getCategoryId(); + if (!categories.containsKey(category)) + categories.put(category, sp.getCategory()); + } + + if (onlyVisible) { + List visibleCategoriesI18n = new ArrayList<>(); + for (int i = 0; i < psp.getTable().getSheetModel().getRowCount(); i++) { + Item o = (Item) psp.getTable().getSheetModel().getObject(i); + if (o.hasToggle()) { // Is a category + if (!visibleCategoriesI18n.contains(o.getName())) { + visibleCategoriesI18n.add(o.getName()); //I18n name + } + } else if (!o.hasToggle() && o.getParent() != null) { + if (!visibleCategoriesI18n.contains(o.getParent().getName())) { + visibleCategoriesI18n.add(o.getParent().getName()); //I18n name + } + } + } + + categories = categories.entrySet().stream().filter(e -> visibleCategoriesI18n.contains(e.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + return categories; + } + + private Future> askForCategories() { + return askForCategories(null); + } + + private Future> askForCategories(Map previousCheckCategoriesOnPanel) { + CompletableFuture> future = new CompletableFuture<>(); + Map categories = getCategoriesOnPanel(true); + List chosenCategories = new ArrayList<>(categories.keySet()); + List checkBoxes = new ArrayList<>(); + for (String category : chosenCategories.stream().sorted().collect(Collectors.toList())) { + JCheckBox cb = new JCheckBox(categories.get(category)); + cb.addActionListener(e -> { + if (((JCheckBox) e.getSource()).isSelected()) { + if (!chosenCategories.contains(category)) + chosenCategories.add(category); + } else { + chosenCategories.remove(category); + } + }); + cb.doClick(); // To set ticked; + if (previousCheckCategoriesOnPanel != null && !previousCheckCategoriesOnPanel.containsKey(category)) { + cb.setSelected(true); + } + checkBoxes.add(cb); + } + categoriesPanel.removeAll(); + categoriesPanel.setLayout(new MigLayout("align center, fill, insets 50")); + + JPanel checklistPanels = new JPanel(new MigLayout("fillx, wrap 2", "[left]rel[grow,fill]", "[]10[]")); + JScrollPane scrollPane = new JScrollPane(checklistPanels); + categoriesPanel.add(scrollPane, "spanx, grow, wrap"); + for (JCheckBox cb : checkBoxes) { + checklistPanels.add(cb, ""); + } + + JPanel selButtonsPanel = new JPanel(new MigLayout("alignx leading", "[center]rel[]", "[]10[]")); + JButton selectAllButton = new JButton(I18n.text("Sel All")); + JButton selectNoneButton = new JButton(I18n.text("Sel None")); + selButtonsPanel.add(selectAllButton, "sg selection, center"); + selButtonsPanel.add(selectNoneButton, "sg selection"); + categoriesPanel.add(selButtonsPanel, "wrap"); + selectAllButton.addActionListener(e -> { + checkBoxes.forEach(cb -> { + if (!cb.isSelected()) { + cb.doClick(); + } + }); + }); + selectNoneButton.addActionListener(e -> { + checkBoxes.forEach(cb -> { + if (cb.isSelected()) { + cb.doClick(); + } + }); + }); + + JPanel okButtonsPanel = new JPanel(new MigLayout("alignx trailing", "[]rel[right]", "[]10[]")); + JButton okButton = new JButton(I18n.text("Ok")); + JButton cancelButton = new JButton(I18n.text("Cancel")); + okButtonsPanel.add(okButton, "gapbefore, sg okcancel, right, tag ok"); + okButtonsPanel.add(cancelButton, "sg okcancel, right, tag cancel"); + categoriesPanel.add(okButtonsPanel, ""); + okButton.addActionListener(e -> { + future.complete(new ArrayList<>(chosenCategories)); + SwingUtilities.getWindowAncestor(categoriesPanel).dispose(); + }); + cancelButton.addActionListener(e -> { + future.completeExceptionally(new RuntimeException("User cancelled")); + SwingUtilities.getWindowAncestor(categoriesPanel).dispose(); + }); + + JDialog dg = new JDialog(SwingUtilities.getWindowAncestor(SystemConfigurationEditorPanel.this), + Dialog.ModalityType.DOCUMENT_MODAL); + dg.setContentPane(categoriesPanel); + dg.setSize(500, 500); + dg.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + dg.getRootPane().registerKeyboardAction(ev -> { dg.dispose(); }, + KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); + GuiUtils.centerParent(dg, (Window) dg.getParent()); + dg.setVisible(true); + + //return new ArrayList<>(categories.keySet()); + return future; + } + /** * This will send to the system the necessary SetEntityParameters messages with SystemProperty message(s) * that are needed. It will only send the SystemProperty messages that are locally dirty. */ private void sendPropertiesToSystem() { + List validCategories = null; + try { + validCategories = askForCategories().get(); + } + catch (Exception e) { + return; + } + Set sentProps = new LinkedHashSet(); ArrayList sysPropToSend = new ArrayList<>(); for (SystemProperty sp : params.values()) { + if (!validCategories.contains(sp.getCategoryId())) + continue; // Skip if not in the list of valid categories if (sp.getTimeDirty() > sp.getTimeSync()) { // sendProperty(sp); sysPropToSend.add(sp); @@ -514,11 +718,20 @@ private void sendPropertiesToSystem() { } private void savePropertiesToSystem() { + List validCategories = null; + try { + validCategories = askForCategories().get(); + } + catch (Exception e) { + return; + } Collection propsInPanel = params.values(); - if (propsInPanel.size() > 0) { + if (!propsInPanel.isEmpty()) { ArrayList secNames = new ArrayList<>(); for (SystemProperty sp : propsInPanel) { String sectionName = sp.getCategoryId(); + if (!validCategories.contains(sectionName)) + continue; // Skip if not in the list of valid categories if (!secNames.contains(sectionName)) secNames.add(sectionName); } @@ -611,7 +824,7 @@ public static void main(String[] args) { final SystemConfigurationEditorPanel sc1 = new SystemConfigurationEditorPanel(vehicle, Scope.MANEUVER, Visibility.USER, true, true, true, ImcMsgManager.getManager()); final SystemConfigurationEditorPanel sc2 = new SystemConfigurationEditorPanel(vehicle, Scope.MANEUVER, - Visibility.USER, true, true, true, ImcMsgManager.getManager()); + Visibility.USER, true, false, true, ImcMsgManager.getManager()); // ImcMsgManager.getManager().addListener(new MessageListener() { // @Override From 7b4c8c50105af29d34edb5486a2dae42da73c3ee Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 27 Nov 2024 17:20:36 +0000 Subject: [PATCH 64/92] params/SystemConfigurationEditorPanel: Tweak interface for category selection. --- .../SystemConfigurationEditorPanel.java | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index 5c8bda40d0..92528d62f4 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -330,7 +330,7 @@ private void updateSendButtons() { actions.add(refreshButton.getAction()); actions.add(saveButton.getAction()); - String suffix = " #"; + String suffix = " >"; for (Action action : actions) { String name = (String) action.getValue("Name"); if (!isAskForCategories && name.endsWith(suffix)) { @@ -437,7 +437,7 @@ private synchronized void refreshPropertiesOnPanel(boolean askForCategories) { if (askForCategories && isAskForCategories) { List validCategories; try { - validCategories = askForCategories(oldCategoriesOnPanel).get(); + validCategories = askForCategories("refresh", oldCategoriesOnPanel).get(); } catch (Exception e) { // Do nothing @@ -593,11 +593,11 @@ private Map getCategoriesOnPanel(boolean onlyVisible) { return categories; } - private Future> askForCategories() { - return askForCategories(null); + private Future> askForCategories(String forWhat) { + return askForCategories(forWhat, null); } - private Future> askForCategories(Map previousCheckCategoriesOnPanel) { + private Future> askForCategories(String forWhat, Map previousCheckCategoriesOnPanel) { CompletableFuture> future = new CompletableFuture<>(); Map categories = getCategoriesOnPanel(true); List chosenCategories = new ArrayList<>(categories.keySet()); @@ -612,49 +612,57 @@ private Future> askForCategories(Map previousCheckC chosenCategories.remove(category); } }); - cb.doClick(); // To set ticked; + cb.setSelected(true); // To set ticked; if (previousCheckCategoriesOnPanel != null && !previousCheckCategoriesOnPanel.containsKey(category)) { cb.setSelected(true); } + // if selected add to checkCategories + if (!chosenCategories.contains(category)) + chosenCategories.add(category); checkBoxes.add(cb); } categoriesPanel.removeAll(); - categoriesPanel.setLayout(new MigLayout("align center, fill, insets 50")); + categoriesPanel.setLayout(new MigLayout("align center, fill, insets 20")); + + JLabel systemLabel = new JLabel(I18n.textf("%systemName Categories", getSystemId())); + systemLabel.setFont(systemLabel.getFont().deriveFont(systemLabel.getFont().getStyle() | java.awt.Font.BOLD)); + JLabel label = new JLabel(I18n.textf("Select the categories to be used for >> %action", forWhat)); + categoriesPanel.add(systemLabel, "wrap"); + categoriesPanel.add(label, "wrap"); JPanel checklistPanels = new JPanel(new MigLayout("fillx, wrap 2", "[left]rel[grow,fill]", "[]10[]")); JScrollPane scrollPane = new JScrollPane(checklistPanels); - categoriesPanel.add(scrollPane, "spanx, grow, wrap"); + categoriesPanel.add(scrollPane, "w 100%, h 100%, wrap"); for (JCheckBox cb : checkBoxes) { checklistPanels.add(cb, ""); } - JPanel selButtonsPanel = new JPanel(new MigLayout("alignx leading", "[center]rel[]", "[]10[]")); JButton selectAllButton = new JButton(I18n.text("Sel All")); JButton selectNoneButton = new JButton(I18n.text("Sel None")); - selButtonsPanel.add(selectAllButton, "sg selection, center"); - selButtonsPanel.add(selectNoneButton, "sg selection"); - categoriesPanel.add(selButtonsPanel, "wrap"); + categoriesPanel.add(selectAllButton, "sg buttons, split"); + categoriesPanel.add(selectNoneButton, "sg buttons, split, gapafter 30"); selectAllButton.addActionListener(e -> { checkBoxes.forEach(cb -> { if (!cb.isSelected()) { - cb.doClick(); + String categoryLabel = cb.getText(); + String category = categories.entrySet().stream() + .filter(ee -> ee.getValue().equals(categoryLabel)) + .map(Map.Entry::getKey).findFirst().orElse(null); + if (!chosenCategories.contains(cb.getText())) + chosenCategories.add(category); + cb.setSelected(true); } }); }); selectNoneButton.addActionListener(e -> { - checkBoxes.forEach(cb -> { - if (cb.isSelected()) { - cb.doClick(); - } - }); + chosenCategories.clear(); + checkBoxes.forEach(cb -> cb.setSelected(false)); }); - JPanel okButtonsPanel = new JPanel(new MigLayout("alignx trailing", "[]rel[right]", "[]10[]")); JButton okButton = new JButton(I18n.text("Ok")); JButton cancelButton = new JButton(I18n.text("Cancel")); - okButtonsPanel.add(okButton, "gapbefore, sg okcancel, right, tag ok"); - okButtonsPanel.add(cancelButton, "sg okcancel, right, tag cancel"); - categoriesPanel.add(okButtonsPanel, ""); + categoriesPanel.add(okButton, "gapbefore push, sg buttons, split"); + categoriesPanel.add(cancelButton, "sg buttons, split"); okButton.addActionListener(e -> { future.complete(new ArrayList<>(chosenCategories)); SwingUtilities.getWindowAncestor(categoriesPanel).dispose(); @@ -685,7 +693,7 @@ private Future> askForCategories(Map previousCheckC private void sendPropertiesToSystem() { List validCategories = null; try { - validCategories = askForCategories().get(); + validCategories = askForCategories("send").get(); } catch (Exception e) { return; @@ -720,7 +728,7 @@ private void sendPropertiesToSystem() { private void savePropertiesToSystem() { List validCategories = null; try { - validCategories = askForCategories().get(); + validCategories = askForCategories("save").get(); } catch (Exception e) { return; From 54664ce0543eaf3aad1fa01b7685a9393ea475f1 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 29 Nov 2024 15:56:46 +0000 Subject: [PATCH 65/92] params/SystemConfigurationEditorPanel: Reworked interface for choose categories. --- .../SystemConfigurationEditorPanel.java | 314 +++++++++++------- 1 file changed, 196 insertions(+), 118 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index 92528d62f4..32dd01fbac 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -34,12 +34,9 @@ import java.awt.CardLayout; import java.awt.Component; -import java.awt.Dialog; -import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; -import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; @@ -59,16 +56,12 @@ import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; -import javax.swing.KeyStroke; import javax.swing.ListCellRenderer; -import javax.swing.SwingUtilities; -import javax.swing.WindowConstants; +import javax.swing.SwingWorker; import com.l2fprod.common.propertysheet.Property; import com.l2fprod.common.propertysheet.PropertyEditorRegistry; @@ -76,8 +69,8 @@ import com.l2fprod.common.propertysheet.PropertySheet; import com.l2fprod.common.propertysheet.PropertySheetPanel; import com.l2fprod.common.propertysheet.PropertySheetTableModel.Item; - import net.miginfocom.swing.MigLayout; + import pt.lsts.imc.EntityParameter; import pt.lsts.imc.EntityParameters; import pt.lsts.imc.IMCMessage; @@ -85,10 +78,12 @@ import pt.lsts.imc.SaveEntityParameters; import pt.lsts.imc.SetEntityParameters; import pt.lsts.neptus.NeptusLog; +import pt.lsts.neptus.comm.IMCSendMessageUtils; import pt.lsts.neptus.comm.manager.imc.ImcMsgManager; import pt.lsts.neptus.comm.manager.imc.ImcSystem; import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; import pt.lsts.neptus.comm.manager.imc.MessageDeliveryListener; +import pt.lsts.neptus.gui.InfiniteProgressPanel; import pt.lsts.neptus.i18n.I18n; import pt.lsts.neptus.params.SystemProperty.Scope; import pt.lsts.neptus.params.SystemProperty.Visibility; @@ -104,13 +99,19 @@ public class SystemConfigurationEditorPanel extends JPanel implements PropertyCh public static final String CARD_PROPERTIES = "properties"; public static final String CARD_CATEGORIES = "categories"; + public static final String CARD_PROGRESS = "progress"; + protected final LinkedHashMap params = new LinkedHashMap<>(); private static boolean isAskForCategories = false; - protected PropertySheetPanel psp; - private JPanel categoriesPanel; private JPanel swapPropertiesAndCategoriesPanel; + private JPanel mainPanel; + private JPanel categoriesPanel; + + private JPanel propertiesPanel; + private InfiniteProgressPanel progressPanel; + protected PropertySheetPanel psp; private JButton sendButton; private JButton saveButton; private JButton refreshButton; @@ -149,6 +150,8 @@ public SystemConfigurationEditorPanel(String systemId, Scope scopeToUse, Visibil private void initialize(boolean showSendButton, boolean showScopeCombo, boolean showResetButton) { setLayout(new MigLayout()); + mainPanel = new JPanel(new MigLayout("fill, insets 0")); + scopeComboBox = new JComboBox(Scope.values()) { public void setSelectedItem(Object anObject) { super.setSelectedItem(anObject); @@ -188,7 +191,7 @@ public void run() { }); titleLabel = new JLabel("" + createTitle() + ""); - add(titleLabel, "w 100%, wrap"); + mainPanel.add(titleLabel, "w 100%, wrap"); // Configure Property sheet psp = new PropertySheetPanel(); @@ -200,43 +203,73 @@ public void run() { resetPropertiesEditorAndRendererFactories(); + propertiesPanel = new JPanel(new CardLayout()); + propertiesPanel.add(psp, CARD_PROPERTIES); + progressPanel = new InfiniteProgressPanel(I18n.text("Please wait...")); + propertiesPanel.add(progressPanel, CARD_PROGRESS); + + mainPanel.add(propertiesPanel, "w 100%, h 100%, wrap"); + categoriesPanel = new JPanel(new MigLayout("fill, insets 0")); swapPropertiesAndCategoriesPanel = new JPanel(new CardLayout()); - swapPropertiesAndCategoriesPanel.add(psp, CARD_PROPERTIES); - //swapPropertiesAndCategoriesPanel.add(categoriesPanel, CARD_CATEGORIES); + //swapPropertiesAndCategoriesPanel.add(psp, CARD_PROPERTIES); + swapPropertiesAndCategoriesPanel.add(mainPanel, CARD_PROPERTIES); + swapPropertiesAndCategoriesPanel.add(categoriesPanel, CARD_CATEGORIES); - add(swapPropertiesAndCategoriesPanel, "w 100%, h 100%, wrap"); + //add(swapPropertiesAndCategoriesPanel, "w 100%, h 100%, wrap"); + add(swapPropertiesAndCategoriesPanel, "w 100%, h 100%"); sendButton = new JButton(new AbstractAction(I18n.text("Send")) { @Override public void actionPerformed(ActionEvent e) { - sendPropertiesToSystem(); + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + sendPropertiesToSystem(); + return null; + } + }; + worker.execute(); } }); sendButton.setToolTipText(I18n.text("Send the modified properties.")); if (showSendButton) { - add(sendButton, "sg buttons, split"); + mainPanel.add(sendButton, "sg buttons, split"); } refreshButton = new JButton(new AbstractAction(I18n.text("Refresh")) { @Override public void actionPerformed(ActionEvent e) { - refreshPropertiesOnPanel(true); + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + refreshPropertiesOnPanel(true); + return null; + } + }; + worker.execute(); } }); refreshButton.setToolTipText(I18n.text("Requests the entities sections parameters from the vehicle.")); - add(refreshButton, "sg buttons, split"); + mainPanel.add(refreshButton, "sg buttons, split"); saveButton = new JButton(new AbstractAction(I18n.text("Save")) { @Override public void actionPerformed(ActionEvent e) { - savePropertiesToSystem(); + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + savePropertiesToSystem(); + return null; + } + }; + worker.execute(); } }); saveButton.setToolTipText(I18n.text("Saves the visible entities sections in the vehicle.")); if (showSendButton) { - add(saveButton, "sg buttons, split"); + mainPanel.add(saveButton, "sg buttons, split"); } collapseButton = new JButton(new AbstractAction(I18n.text("Collapse All")) { @@ -251,7 +284,7 @@ public void actionPerformed(ActionEvent e) { } }); collapseButton.setToolTipText(I18n.text("Collapse all sections.")); - add(collapseButton, "sg buttons"); + mainPanel.add(collapseButton, "sg buttons, gapbefore unrel"); expandButton = new JButton(new AbstractAction(I18n.text("Expand All")) { @Override @@ -269,7 +302,7 @@ public void actionPerformed(ActionEvent e) { } }); expandButton.setToolTipText(I18n.text("Expand all sections.")); - add(expandButton, "sg buttons, split"); + mainPanel.add(expandButton, "sg buttons, split"); resetButton = new JButton(new AbstractAction(I18n.text("Reset")) { @Override @@ -279,16 +312,16 @@ public void actionPerformed(ActionEvent e) { }); resetButton.setToolTipText(I18n.text("Local reset. Needs to be sent to system.")); if (showResetButton) - add(resetButton, "sg buttons, gapbefore 30, split, wrap"); + mainPanel.add(resetButton, "sg buttons, gapbefore 30, split, wrap"); resetButton.setToolTipText(I18n.text("Local reset. Needs to be sent to system.")); if (showScopeCombo) - add(scopeComboBox, "split, w :160:"); + mainPanel.add(scopeComboBox, "split, w :160:"); checkAdvance = new JCheckBox(I18n.text("Access Developer Parameters")); checkAdvance.setToolTipText("" + I18n.textc("Be careful changing these values.
They may make the vehicle inoperable.", "This will be a tooltip, and use
to change line.")); - add(checkAdvance, "split, sg checkboxes"); + mainPanel.add(checkAdvance, "split, sg checkboxes"); if (visibility == Visibility.DEVELOPER) checkAdvance.setSelected(true); else @@ -302,7 +335,14 @@ public void itemStateChanged(ItemEvent e) { visibility = Visibility.USER; // FIXME This might not make sense to not always ask for categories - refreshPropertiesOnPanel(true); + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + refreshPropertiesOnPanel(false); + return null; + } + }; + worker.execute(); } }); checkAdvance.setFocusable(false); @@ -316,8 +356,9 @@ public void itemStateChanged(ItemEvent e) { }); checkSelection.setSelected(isAskForCategories); checkSelection.setFocusable(false); - add(checkSelection, "sg checkboxes"); + mainPanel.add(checkSelection, "sg checkboxes"); + // FIXME This might not make sense to not always ask for categories if no wifi refreshPropertiesOnPanel(false); revalidate(); @@ -390,73 +431,88 @@ public void setRefreshing(boolean refreshing) { } private synchronized void refreshPropertiesOnPanel(boolean askForCategories) { - // FIXME - Map oldCategoriesOnPanel = getCategoriesOnPanel(true); + try { + showWaiterUpdateProperties(true); - titleLabel.setText("" + createTitle() + ""); - List openCategories = removeAllPropertiesFromPanel(); - - resetPropertiesEditorAndRendererFactories(); - - ArrayList pr = ConfigurationManager.getInstance().getProperties(systemId, visibility, scopeToUse); - ArrayList secNames = new ArrayList<>(); - for (SystemProperty sp : pr) { - String sectionName = sp.getCategoryId(); - String name = sp.getName(); - if (!secNames.contains(sectionName)) - secNames.add(sectionName); - params.put(sectionName + "." + name, sp); - sp.addPropertyChangeListener(this); - psp.addProperty(sp); - if (sp.getEditor() != null) { - per.registerEditor(sp, sp.getEditor()); - } - if (sp.getRenderer() != null) { - prr.registerRenderer(sp, sp.getRenderer()); + // FIXME + Map oldCategoriesOnPanel = getCategoriesOnPanel(true); + + titleLabel.setText("" + createTitle() + ""); + List openCategories = removeAllPropertiesFromPanel(); + + resetPropertiesEditorAndRendererFactories(); + + ArrayList pr = ConfigurationManager.getInstance().getProperties(systemId, visibility, scopeToUse); + ArrayList secNames = new ArrayList<>(); + for (SystemProperty sp : pr) { + String sectionName = sp.getCategoryId(); + String name = sp.getName(); + if (!secNames.contains(sectionName)) + secNames.add(sectionName); + params.put(sectionName + "." + name, sp); + sp.addPropertyChangeListener(this); + psp.addProperty(sp); + if (sp.getEditor() != null) { + per.registerEditor(sp, sp.getEditor()); + } + if (sp.getRenderer() != null) { + prr.registerRenderer(sp, sp.getRenderer()); + } } - } - // Let us make sure all dependencies between properties are ok - for (SystemProperty spCh : params.values()) { - for (SystemProperty sp : params.values()) { - PropertyChangeEvent evt = new PropertyChangeEvent(spCh, spCh.getName(), null, spCh.getValue()); - sp.propertyChange(evt); + // Let us make sure all dependencies between properties are ok + for (SystemProperty spCh : params.values()) { + for (SystemProperty sp : params.values()) { + PropertyChangeEvent evt = new PropertyChangeEvent(spCh, spCh.getName(), null, spCh.getValue()); + sp.propertyChange(evt); + } } - } - // Close all categories - for (int i = 0; i < psp.getTable().getSheetModel().getRowCount(); i++) { - Item o = (Item) psp.getTable().getSheetModel().getObject(i); - if (o.isVisible() && !o.hasToggle()) { - if (!openCategories.contains(o.getParent().getName())) { - o.getParent().toggle(); + // Close all categories + for (int i = 0; i < psp.getTable().getSheetModel().getRowCount(); i++) { + Item o = (Item) psp.getTable().getSheetModel().getObject(i); + if (o.isVisible() && !o.hasToggle()) { + if (!openCategories.contains(o.getParent().getName())) { + o.getParent().toggle(); + } } } - } - List queryCategoriesList; - if (askForCategories && isAskForCategories) { - List validCategories; - try { - validCategories = askForCategories("refresh", oldCategoriesOnPanel).get(); - } - catch (Exception e) { - // Do nothing - validCategories = Collections.emptyList(); + List queryCategoriesList; + if (askForCategories && isAskForCategories) { + List validCategories; + try { + validCategories = askForCategories("refresh", oldCategoriesOnPanel).get(); + } + catch (Exception e) { + // Do nothing + validCategories = Collections.emptyList(); + } + queryCategoriesList = new ArrayList<>(); + for (String category : validCategories) { + if (category != null && validCategories.contains(category)) + queryCategoriesList.add(category); + } + } else { + queryCategoriesList = secNames; } - queryCategoriesList = new ArrayList<>(); - for (String category : validCategories) { - if (category != null && validCategories.contains(category)) - queryCategoriesList.add(category); + + showWaiterUpdateProperties(false); + revalidate(); + repaint(); + + for (String sectionName : queryCategoriesList) { + boolean ret = queryValues(sectionName, scopeToUse.getText(), visibility.getText()); + if (!ret) + break; } - } else { - queryCategoriesList = secNames; } - for (String sectionName : queryCategoriesList) { - queryValues(sectionName, scopeToUse.getText(), visibility.getText()); + catch (Exception e) { + NeptusLog.pub().error(e); + } finally { + showWaiterUpdateProperties(false); + revalidate(); + repaint(); } - - revalidate(); - repaint(); } private synchronized void resetPropertiesOnPanel() { @@ -486,6 +542,11 @@ private List removeAllPropertiesFromPanel() { return toggledCategories; } + private void showWaiterUpdateProperties(boolean wait) { + ((CardLayout) propertiesPanel.getLayout()).show(propertiesPanel, wait ? CARD_PROGRESS : CARD_PROPERTIES); + progressPanel.setBusy(wait); + } + private String createTitle() { return I18n.textf("%systemName Parameters", getSystemId() == null ? "" : getSystemId()); } @@ -507,22 +568,22 @@ public void propertyChange(PropertyChangeEvent evt) { } } - private void queryValues(String entityName, String scope, String visibility) { + private boolean queryValues(String entityName, String scope, String visibility) { QueryEntityParameters qep = new QueryEntityParameters(); qep.setScope(scope); qep.setVisibility(visibility); qep.setName(entityName); - send(qep); + return send(qep); } - private void saveRequest(String entityName) { + private boolean saveRequest(String entityName) { SaveEntityParameters qep = new SaveEntityParameters(); qep.setName(entityName); - send(qep); + return send(qep); } private void sendProperty(SystemProperty... propsList) { - Map> mapCategoryParameterList = new LinkedHashMap>(); + Map> mapCategoryParameterList = new LinkedHashMap>(); for (SystemProperty prop : propsList) { if (prop.getValue() == null) continue; @@ -559,7 +620,8 @@ private void sendProperty(SystemProperty... propsList) { } for (SetEntityParameters setEntityParameters : msgs) { - send(setEntityParameters); + if (!send(setEntityParameters)) + break; } } @@ -622,9 +684,10 @@ private Future> askForCategories(String forWhat, Map" + createTitle() + ""); - JLabel systemLabel = new JLabel(I18n.textf("%systemName Categories", getSystemId())); systemLabel.setFont(systemLabel.getFont().deriveFont(systemLabel.getFont().getStyle() | java.awt.Font.BOLD)); JLabel label = new JLabel(I18n.textf("Select the categories to be used for >> %action", forWhat)); categoriesPanel.add(systemLabel, "wrap"); @@ -665,24 +728,27 @@ private Future> askForCategories(String forWhat, Map { future.complete(new ArrayList<>(chosenCategories)); - SwingUtilities.getWindowAncestor(categoriesPanel).dispose(); + // SwingUtilities.getWindowAncestor(categoriesPanel).dispose(); + CardLayout card = (CardLayout) swapPropertiesAndCategoriesPanel.getLayout(); + card.show(swapPropertiesAndCategoriesPanel, CARD_PROPERTIES); + revalidate(); + repaint(); }); cancelButton.addActionListener(e -> { future.completeExceptionally(new RuntimeException("User cancelled")); - SwingUtilities.getWindowAncestor(categoriesPanel).dispose(); + // SwingUtilities.getWindowAncestor(categoriesPanel).dispose(); + CardLayout card = (CardLayout) swapPropertiesAndCategoriesPanel.getLayout(); + card.show(swapPropertiesAndCategoriesPanel, CARD_PROPERTIES); + revalidate(); + repaint(); }); + GuiUtils.reactEnterKeyPress(okButton); + GuiUtils.reactEscapeKeyPress(cancelButton); - JDialog dg = new JDialog(SwingUtilities.getWindowAncestor(SystemConfigurationEditorPanel.this), - Dialog.ModalityType.DOCUMENT_MODAL); - dg.setContentPane(categoriesPanel); - dg.setSize(500, 500); - dg.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - dg.getRootPane().registerKeyboardAction(ev -> { dg.dispose(); }, - KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); - GuiUtils.centerParent(dg, (Window) dg.getParent()); - dg.setVisible(true); - - //return new ArrayList<>(categories.keySet()); + CardLayout card = (CardLayout) swapPropertiesAndCategoriesPanel.getLayout(); + card.show(swapPropertiesAndCategoriesPanel, CARD_CATEGORIES); + revalidate(); + repaint(); return future; } @@ -720,7 +786,8 @@ private void sendPropertiesToSystem() { secNames.add(sectionName); } for (String sec : secNames) { - queryValues(sec, scopeToUse.getText(), visibility.getText()); + if (!queryValues(sec, scopeToUse.getText(), visibility.getText())) + break; } } } @@ -742,18 +809,24 @@ private void savePropertiesToSystem() { continue; // Skip if not in the list of valid categories if (!secNames.contains(sectionName)) secNames.add(sectionName); - } - for (String sec : secNames) { - queryValues(sec, scopeToUse.getText(), visibility.getText()); } - + boolean ret = true; for (String sec : secNames) { - saveRequest(sec); + ret = queryValues(sec, scopeToUse.getText(), visibility.getText()); + if (!ret) + break; + } + + if (ret) { + for (String sec : secNames) { + if (!saveRequest(sec)) + break; + } } } } - private void send(IMCMessage msg) { + private boolean send(IMCMessage msg) { //}, boolean askApprovalOtherThanWifi) { MessageDeliveryListener mdl = new MessageDeliveryListener() { @Override public void deliveryUnreacheable(IMCMessage message) { @@ -777,12 +850,17 @@ public void deliveryError(IMCMessage message, Object error) { }; if (sid == null) sid = ImcSystemsHolder.getSystemWithName(getSystemId()); - if (sid != null) { - imcMsgManager.sendReliablyNonBlocking(msg, sid.getId(), mdl); - } - else { - imcMsgManager.sendMessageToSystem(msg, getSystemId()); - } + boolean sendReliably = sid != null; + String system = sid != null ? sid.getName() : systemId; +// if (sid != null) { +// imcMsgManager.sendReliablyNonBlocking(msg, sid.getId(), mdl); +// } +// else { +// imcMsgManager.sendMessageToSystem(msg, getSystemId()); +// } + return IMCSendMessageUtils.sendMessage(msg, (sendReliably ? ImcMsgManager.TRANSPORT_TCP + : null), mdl, this, I18n.text("Error sending msg params"), + false, "", true, true, true, system); } public static void updatePropertyWithMessageArrived(SystemConfigurationEditorPanel systemConfEditor, IMCMessage message) { From 41b24382fb942fd85de910697858423d9bba1269 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 9 Dec 2024 15:13:20 +0000 Subject: [PATCH 66/92] util/conf/GeneralPreferences: Fix typo. --- src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java | 8 ++++---- src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java index a5ae008fcc..38122746e2 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java @@ -120,10 +120,10 @@ public void run() { return; } running = true; - double poolIntervalMin = Math.max(0.17, Math.min(30, GeneralPreferences.iridiumMessengerPoolMinutes)); - Duration poolInterval = poolIntervalMin >= 1 ? Duration.ofMinutes((long) poolIntervalMin) - : Duration.ofSeconds((long) (60 * poolIntervalMin)); - if (lastCall != null && System.currentTimeMillis() - lastCall.getTime() < poolInterval.toMillis()) { + double pollIntervalMin = Math.max(0.17, Math.min(30, GeneralPreferences.iridiumMessengerPollMinutes)); + Duration pollInterval = pollIntervalMin >= 1 ? Duration.ofMinutes((long) pollIntervalMin) + : Duration.ofSeconds((long) (60 * pollIntervalMin)); + if (lastCall != null && System.currentTimeMillis() - lastCall.getTime() < pollInterval.toMillis()) { return; } diff --git a/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java b/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java index 4946189cf3..782dc56908 100644 --- a/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java +++ b/src/java/pt/lsts/neptus/util/conf/GeneralPreferences.java @@ -246,10 +246,10 @@ public class GeneralPreferences implements PropertiesProvider { @NeptusProperty(name = "Iridium Messenger", category="Iridium Communications", userLevel = LEVEL.REGULAR, description = "Iridium messaging implementation") public static IridiumMessengerEnum iridiumMessenger = IridiumMessengerEnum.HubIridiumMessenger; - @NeptusProperty(name = "Iridium Messenger Pool Messages", category="Iridium Communications", userLevel = LEVEL.REGULAR, - description = "Iridium messaging pool messages in minutes. Valid values between 0.17 (~10s) and 30. Doesn't need restart to apply", + @NeptusProperty(name = "Iridium Messenger Poll Messages", category="Iridium Communications", userLevel = LEVEL.REGULAR, + description = "Iridium messaging poll messages in minutes. Valid values between 0.17 (~10s) and 30. Doesn't need restart to apply", units = "minutes") - public static double iridiumMessengerPoolMinutes = 5; + public static double iridiumMessengerPollMinutes = 5; // ------------------------------------------------------------------------- From 4ce9863b53abd64458c309f5516e9dc6649270be Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Mon, 9 Dec 2024 15:14:00 +0000 Subject: [PATCH 67/92] comm/iridium/IridiumManager: Cleanup. --- src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java index 38122746e2..64af52bbd5 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java @@ -133,7 +133,7 @@ public void run() { Collection msgs = getCurrentMessenger().pollMessages(lastTime); NeptusLog.pub().info("Polled {} messages from Iridium network.", msgs.size()); - if (!msgs.isEmpty()) { + if (!msgs.isEmpty()) { speakUpdateEntityState(); } for (IridiumMessage m : msgs) { From d2a67917bfbe3b41d8337aa41b940c14a91be6ed Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 10 Dec 2024 13:50:47 +0000 Subject: [PATCH 68/92] comm/manager/imc/ImcMsgManager: Fix to use the channelsToSend passed in the method. --- src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java index 1d611698f0..5f9db08ce3 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManager.java @@ -1190,7 +1190,7 @@ public Future sendMessageUsingActiveChannel(IMCMessage message, Stri timeoutMillis = timeoutMillis < 0 ? CommsAdmin.COMM_TIMEOUT_MILLIS : timeoutMillis; Future ret = commsAdmin.sendMessage(message, destinationName, timeoutMillis, - parentComponentForAlert, requireUserConfirmOtherThanWifi); + parentComponentForAlert, requireUserConfirmOtherThanWifi, channelsToSend); return ret; } From 59a35fc17e051805e2d643921c803463a6828212 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 10 Dec 2024 13:53:24 +0000 Subject: [PATCH 69/92] comm/IMCSendMessageUtils: Added option to pass also channels to use to send, and also not to popup GUI on error. --- .../lsts/neptus/comm/IMCSendMessageUtils.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/IMCSendMessageUtils.java b/src/java/pt/lsts/neptus/comm/IMCSendMessageUtils.java index 833dbbaeb8..73bcb4b296 100644 --- a/src/java/pt/lsts/neptus/comm/IMCSendMessageUtils.java +++ b/src/java/pt/lsts/neptus/comm/IMCSendMessageUtils.java @@ -122,6 +122,20 @@ public static boolean sendMessage(IMCMessage msg, Component parent, String error acousticOpUseOnlyActive, acousticOpUserAprovedQuestion, sendOnlyThroughOneAcoustically, ids); } + public static boolean sendMessage(IMCMessage msg, String sendProperties, MessageDeliveryListener listener, Component parent, String errorTextForDialog, + boolean ignoreAcousticSending, String acousticOpServiceName, boolean acousticOpUseOnlyActive, + boolean acousticOpUserApprovedQuestion, boolean sendOnlyThroughOneAcoustically, String... ids) { + return sendMessage(msg, sendProperties, listener, parent, errorTextForDialog, ignoreAcousticSending, acousticOpServiceName, + acousticOpUseOnlyActive, acousticOpUserApprovedQuestion, sendOnlyThroughOneAcoustically, true, new String[0], ids); + } + + public static boolean sendMessage(IMCMessage msg, String sendProperties, MessageDeliveryListener listener, Component parent, String errorTextForDialog, + boolean ignoreAcousticSending, String acousticOpServiceName, boolean acousticOpUseOnlyActive, + boolean acousticOpUserApprovedQuestion, boolean sendOnlyThroughOneAcoustically, boolean popGuiOnError, String... ids) { + return sendMessage(msg, sendProperties, listener, parent, errorTextForDialog, ignoreAcousticSending, acousticOpServiceName, + acousticOpUseOnlyActive, acousticOpUserApprovedQuestion, sendOnlyThroughOneAcoustically, popGuiOnError, new String[0], ids); + } + /** * @param msg * @param sendProperties The same of {@link ImcMsgManager#sendMessage(IMCMessage, pt.lsts.neptus.comm.manager.imc.ImcId16, String, pt.lsts.neptus.comm.manager.imc.MessageDeliveryListener)}, @@ -129,28 +143,29 @@ public static boolean sendMessage(IMCMessage msg, Component parent, String error * @param parent The parent component for popup error message * @param errorTextForDialog * @param ignoreAcousticSending If this is true mean don't use acoustic. - * @param acousticOpServiceName + * @param acousticOpServiceName * @param acousticOpUseOnlyActive - * @param acousticOpUserAprovedQuestion + * @param acousticOpUserApprovedQuestion * @param ids * @return */ public static boolean sendMessage(IMCMessage msg, String sendProperties, MessageDeliveryListener listener, Component parent, String errorTextForDialog, boolean ignoreAcousticSending, String acousticOpServiceName, boolean acousticOpUseOnlyActive, - boolean acousticOpUserAprovedQuestion, boolean sendOnlyThroughOneAcoustically, String... ids) { + boolean acousticOpUserApprovedQuestion, boolean sendOnlyThroughOneAcoustically, boolean popGuiOnError, String[] channelsToSend, String... ids) { ImcSystem[] acousticOpSysLst = !ignoreAcousticSending ? ImcSystemsHolder.lookupSystemByService( acousticOpServiceName, SystemTypeEnum.ALL, acousticOpUseOnlyActive) : new ImcSystem[0]; - boolean acousticOpUserAprovalRequired = acousticOpUserAprovedQuestion; - boolean acousticOpUserAproved = !acousticOpUserAprovedQuestion; + boolean acousticOpUserAprovalRequired = acousticOpUserApprovedQuestion; + boolean acousticOpUserAproved = !acousticOpUserApprovedQuestion; boolean retAll = true; for (String sid : ids) { boolean ret; ImcSystem sysL = ImcSystemsHolder.lookupSystemByName(sid); if (GeneralPreferences.imcUseNewMultiChannelCommsEnable && sysL != null && !sysL.isActive()) { - ret = ImcMsgManager.getManager().sendMessageUsingActiveChannelWait(msg, sid, -1, parent, acousticOpUserAprovedQuestion); + ret = ImcMsgManager.getManager().sendMessageUsingActiveChannelWait(msg, sid, -1, parent, + acousticOpUserApprovedQuestion, channelsToSend); if (ret) { acousticOpUserAproved = true; } @@ -171,11 +186,12 @@ else if (acousticOpSysLst.length != 0 && sysL != null && !sysL.isActive()) { } retAll = retAll && ret; if (!ret) { - if (parent instanceof ConsolePanel) { + NeptusLog.pub().warn(errorTextForDialog); + if (popGuiOnError && parent instanceof ConsolePanel) { ((ConsolePanel) parent).post(Notification.error(I18n.text("Send Message"), errorTextForDialog).src( I18n.text("Console"))); } - else { + else if (popGuiOnError && parent != null) { GuiUtils.errorMessage(parent, I18n.text("Send Message"), errorTextForDialog); } } From ca8309f14900299df1290dce020b507d353a6e74 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 10 Dec 2024 13:55:57 +0000 Subject: [PATCH 70/92] params/SystemConfigurationEditorPanel: Added option to make choice of channels to use, to decrease the number of messages sent by Iridium without user intervention. --- .../SystemConfigurationEditorPanel.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index 32dd01fbac..08d654aaa6 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -79,6 +79,7 @@ import pt.lsts.imc.SetEntityParameters; import pt.lsts.neptus.NeptusLog; import pt.lsts.neptus.comm.IMCSendMessageUtils; +import pt.lsts.neptus.comm.admin.CommsAdmin; import pt.lsts.neptus.comm.manager.imc.ImcMsgManager; import pt.lsts.neptus.comm.manager.imc.ImcSystem; import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; @@ -244,7 +245,7 @@ public void actionPerformed(ActionEvent e) { SwingWorker worker = new SwingWorker() { @Override protected Void doInBackground() throws Exception { - refreshPropertiesOnPanel(true); + refreshPropertiesOnPanel(true, true, new String[] {CommsAdmin.CommChannelType.WIFI.name}); return null; } }; @@ -338,7 +339,7 @@ public void itemStateChanged(ItemEvent e) { SwingWorker worker = new SwingWorker() { @Override protected Void doInBackground() throws Exception { - refreshPropertiesOnPanel(false); + refreshPropertiesOnPanel(false, false, new String[] {CommsAdmin.CommChannelType.WIFI.name}); return null; } }; @@ -359,7 +360,7 @@ protected Void doInBackground() throws Exception { mainPanel.add(checkSelection, "sg checkboxes"); // FIXME This might not make sense to not always ask for categories if no wifi - refreshPropertiesOnPanel(false); + refreshPropertiesOnPanel(false, false, new String[] {CommsAdmin.CommChannelType.WIFI.name}); revalidate(); repaint(); @@ -413,7 +414,7 @@ public void setSystemId(String systemId) { this.systemId = systemId; sid = ImcSystemsHolder.getSystemWithName(this.systemId); // FIXME This might not make sense to not always ask for categories - refreshPropertiesOnPanel(true); + refreshPropertiesOnPanel(false, false, new String[]{CommsAdmin.CommChannelType.WIFI.name}); } /** @@ -430,7 +431,7 @@ public void setRefreshing(boolean refreshing) { this.refreshing = refreshing; } - private synchronized void refreshPropertiesOnPanel(boolean askForCategories) { + private synchronized void refreshPropertiesOnPanel(boolean askForCategories, boolean popGuiOnError, String[] channelsToUse) { try { showWaiterUpdateProperties(true); @@ -501,7 +502,7 @@ private synchronized void refreshPropertiesOnPanel(boolean askForCategories) { repaint(); for (String sectionName : queryCategoriesList) { - boolean ret = queryValues(sectionName, scopeToUse.getText(), visibility.getText()); + boolean ret = queryValues(sectionName, scopeToUse.getText(), visibility.getText(), popGuiOnError, channelsToUse); if (!ret) break; } @@ -568,18 +569,18 @@ public void propertyChange(PropertyChangeEvent evt) { } } - private boolean queryValues(String entityName, String scope, String visibility) { + private boolean queryValues(String entityName, String scope, String visibility, boolean popGuiOnError, String... channelsToUse) { QueryEntityParameters qep = new QueryEntityParameters(); qep.setScope(scope); qep.setVisibility(visibility); qep.setName(entityName); - return send(qep); + return send(qep, popGuiOnError, channelsToUse); } private boolean saveRequest(String entityName) { SaveEntityParameters qep = new SaveEntityParameters(); qep.setName(entityName); - return send(qep); + return send(qep, true); } private void sendProperty(SystemProperty... propsList) { @@ -620,7 +621,7 @@ private void sendProperty(SystemProperty... propsList) { } for (SetEntityParameters setEntityParameters : msgs) { - if (!send(setEntityParameters)) + if (!send(setEntityParameters, true)) break; } } @@ -786,7 +787,8 @@ private void sendPropertiesToSystem() { secNames.add(sectionName); } for (String sec : secNames) { - if (!queryValues(sec, scopeToUse.getText(), visibility.getText())) + // TODO See if we want to ask back from Iridium + if (!queryValues(sec, scopeToUse.getText(), visibility.getText(), true)) break; } } @@ -812,7 +814,8 @@ private void savePropertiesToSystem() { } boolean ret = true; for (String sec : secNames) { - ret = queryValues(sec, scopeToUse.getText(), visibility.getText()); + // TODO See if we want to ask back from Iridium + ret = queryValues(sec, scopeToUse.getText(), visibility.getText(), true); if (!ret) break; } @@ -826,7 +829,7 @@ private void savePropertiesToSystem() { } } - private boolean send(IMCMessage msg) { //}, boolean askApprovalOtherThanWifi) { + private boolean send(IMCMessage msg, boolean popGuiOnError, String... channelsToUse) { //}, boolean askApprovalOtherThanWifi) { MessageDeliveryListener mdl = new MessageDeliveryListener() { @Override public void deliveryUnreacheable(IMCMessage message) { @@ -860,7 +863,8 @@ public void deliveryError(IMCMessage message, Object error) { // } return IMCSendMessageUtils.sendMessage(msg, (sendReliably ? ImcMsgManager.TRANSPORT_TCP : null), mdl, this, I18n.text("Error sending msg params"), - false, "", true, true, true, system); + false, "", true, true, + true, popGuiOnError, channelsToUse, system); } public static void updatePropertyWithMessageArrived(SystemConfigurationEditorPanel systemConfEditor, IMCMessage message) { From af5494365dea46f3eab3546354928cbdb6aeddd0 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 10 Dec 2024 14:29:23 +0000 Subject: [PATCH 71/92] params/SystemConfigurationEditorPanel: Cleanup. --- .../neptus/params/SystemConfigurationEditorPanel.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index 08d654aaa6..191ec9282c 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -181,13 +181,10 @@ public Component getListCellRendererComponent(JList list, Scope @Override public void itemStateChanged(ItemEvent e) { scopeToUse = (Scope) e.getItem(); - new Thread() { - @Override - public void run() { - if (refreshButton != null) - refreshButton.doClick(50); - } - }.start(); + new Thread(() -> { + if (refreshButton != null) + refreshButton.doClick(50); + }).start(); } }); From 6add76a7b1bc0053c5f43c86630e977b14f8c52c Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 10 Dec 2024 14:34:03 +0000 Subject: [PATCH 72/92] params/SystemConfigurationEditorPanel: Cleanup. --- .../pt/lsts/neptus/params/SystemConfigurationEditorPanel.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index 191ec9282c..b1eff46089 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -211,11 +211,9 @@ public void itemStateChanged(ItemEvent e) { categoriesPanel = new JPanel(new MigLayout("fill, insets 0")); swapPropertiesAndCategoriesPanel = new JPanel(new CardLayout()); - //swapPropertiesAndCategoriesPanel.add(psp, CARD_PROPERTIES); swapPropertiesAndCategoriesPanel.add(mainPanel, CARD_PROPERTIES); swapPropertiesAndCategoriesPanel.add(categoriesPanel, CARD_CATEGORIES); - //add(swapPropertiesAndCategoriesPanel, "w 100%, h 100%, wrap"); add(swapPropertiesAndCategoriesPanel, "w 100%, h 100%"); sendButton = new JButton(new AbstractAction(I18n.text("Send")) { From 6b998ea7588eb33afc8e338cc152c4c9b5cf2f6c Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 10 Dec 2024 14:34:32 +0000 Subject: [PATCH 73/92] params/SystemConfigurationEditorPanel: Cleanup. --- .../SystemConfigurationEditorPanel.java | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index b1eff46089..e195cf65a0 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -322,24 +322,21 @@ public void actionPerformed(ActionEvent e) { checkAdvance.setSelected(true); else checkAdvance.setSelected(false); - checkAdvance.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - if (checkAdvance.isSelected()) - visibility = Visibility.DEVELOPER; - else - visibility = Visibility.USER; - - // FIXME This might not make sense to not always ask for categories - SwingWorker worker = new SwingWorker() { - @Override - protected Void doInBackground() throws Exception { - refreshPropertiesOnPanel(false, false, new String[] {CommsAdmin.CommChannelType.WIFI.name}); - return null; - } - }; - worker.execute(); - } + checkAdvance.addItemListener(e -> { + if (checkAdvance.isSelected()) + visibility = Visibility.DEVELOPER; + else + visibility = Visibility.USER; + + // FIXME This might not make sense to not always ask for categories + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + refreshPropertiesOnPanel(false, false, new String[] {CommsAdmin.CommChannelType.WIFI.name}); + return null; + } + }; + worker.execute(); }); checkAdvance.setFocusable(false); @@ -579,7 +576,7 @@ private boolean saveRequest(String entityName) { } private void sendProperty(SystemProperty... propsList) { - Map> mapCategoryParameterList = new LinkedHashMap>(); + Map> mapCategoryParameterList = new LinkedHashMap<>(); for (SystemProperty prop : propsList) { if (prop.getValue() == null) continue; @@ -772,8 +769,8 @@ private void sendPropertiesToSystem() { sentProps.add(sp); } } - if (sysPropToSend.size() > 0) { - sendProperty(sysPropToSend.toArray(new SystemProperty[sysPropToSend.size()])); + if (!sysPropToSend.isEmpty()) { + sendProperty(sysPropToSend.toArray(new SystemProperty[0])); ArrayList secNames = new ArrayList<>(); for (SystemProperty sp : sentProps) { From f35832b6c50dfb7c8aaa16ab78d7598d0cba3984 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 10 Dec 2024 14:37:05 +0000 Subject: [PATCH 74/92] params/SystemConfigurationEditorPanel: Cleanup. --- .../lsts/neptus/params/SystemConfigurationEditorPanel.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index e195cf65a0..1999b50a06 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -318,10 +318,7 @@ public void actionPerformed(ActionEvent e) { checkAdvance.setToolTipText("" + I18n.textc("Be careful changing these values.
They may make the vehicle inoperable.", "This will be a tooltip, and use
to change line.")); mainPanel.add(checkAdvance, "split, sg checkboxes"); - if (visibility == Visibility.DEVELOPER) - checkAdvance.setSelected(true); - else - checkAdvance.setSelected(false); + checkAdvance.setSelected(visibility == Visibility.DEVELOPER); checkAdvance.addItemListener(e -> { if (checkAdvance.isSelected()) visibility = Visibility.DEVELOPER; From e73783df69fd8925351101ac97448abc73f0d3f8 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 11 Dec 2024 17:31:09 +0000 Subject: [PATCH 75/92] params/SystemConfigurationEditorPanel: Reduce the Iridium msgs if one fails skip the next msgs. --- .../params/SystemConfigurationEditorPanel.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index 1999b50a06..15d3265d3b 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -572,7 +572,7 @@ private boolean saveRequest(String entityName) { return send(qep, true); } - private void sendProperty(SystemProperty... propsList) { + private boolean sendProperty(SystemProperty... propsList) { Map> mapCategoryParameterList = new LinkedHashMap<>(); for (SystemProperty prop : propsList) { if (prop.getValue() == null) @@ -611,8 +611,9 @@ private void sendProperty(SystemProperty... propsList) { for (SetEntityParameters setEntityParameters : msgs) { if (!send(setEntityParameters, true)) - break; + return false; // If one fails, rest is skipped, this helps to avoid iridium to be flooded all errors } + return true; } private Map getCategoriesOnPanel(boolean onlyVisible) { @@ -767,8 +768,12 @@ private void sendPropertiesToSystem() { } } if (!sysPropToSend.isEmpty()) { - sendProperty(sysPropToSend.toArray(new SystemProperty[0])); - + boolean ret = sendProperty(sysPropToSend.toArray(new SystemProperty[0])); + + if (!ret) { + return; + } + ArrayList secNames = new ArrayList<>(); for (SystemProperty sp : sentProps) { String sectionName = sp.getCategoryId(); From 2bcb49c789e690435908f9e9e0f65f8cdcf17cc9 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 11 Dec 2024 17:31:40 +0000 Subject: [PATCH 76/92] params/SystemConfigurationEditorPanel: Saving previous user choices. --- .../SystemConfigurationEditorPanel.java | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java index 15d3265d3b..9160b47ce2 100644 --- a/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java +++ b/src/java/pt/lsts/neptus/params/SystemConfigurationEditorPanel.java @@ -136,7 +136,11 @@ public class SystemConfigurationEditorPanel extends JPanel implements PropertyCh protected ImcSystem sid = null; protected ImcMsgManager imcMsgManager; - + + // Category name, category label on gui + private Map touchedCategoriesList; + private Map lastSelectedCategoriesList; + public SystemConfigurationEditorPanel(String systemId, Scope scopeToUse, Visibility visibility, boolean showSendButton, boolean showScopeCombo, boolean showResetButton, ImcMsgManager imcMsgManager) { this.systemId = systemId; @@ -425,7 +429,7 @@ private synchronized void refreshPropertiesOnPanel(boolean askForCategories, boo showWaiterUpdateProperties(true); // FIXME - Map oldCategoriesOnPanel = getCategoriesOnPanel(true); + //Map oldCategoriesOnPanel = getCategoriesOnPanel(true); titleLabel.setText("" + createTitle() + ""); List openCategories = removeAllPropertiesFromPanel(); @@ -471,7 +475,7 @@ private synchronized void refreshPropertiesOnPanel(boolean askForCategories, boo if (askForCategories && isAskForCategories) { List validCategories; try { - validCategories = askForCategories("refresh", oldCategoriesOnPanel).get(); + validCategories = askForCategories("refresh", lastSelectedCategoriesList).get(); } catch (Exception e) { // Do nothing @@ -555,6 +559,10 @@ public void propertyChange(PropertyChangeEvent evt) { sprop.propertyChange(evt); } sp.propertyChange(evt); + + if (touchedCategoriesList == null) + touchedCategoriesList = new LinkedHashMap<>(); + touchedCategoriesList.putIfAbsent(sp.getCategoryId(), sp.getCategory()); } } @@ -655,6 +663,13 @@ private Future> askForCategories(String forWhat, Map categories = getCategoriesOnPanel(true); List chosenCategories = new ArrayList<>(categories.keySet()); List checkBoxes = new ArrayList<>(); + + if ((previousCheckCategoriesOnPanel == null || previousCheckCategoriesOnPanel.isEmpty()) + && lastSelectedCategoriesList != null) { + previousCheckCategoriesOnPanel = new LinkedHashMap<>(); + previousCheckCategoriesOnPanel.putAll(lastSelectedCategoriesList); + } + for (String category : chosenCategories.stream().sorted().collect(Collectors.toList())) { JCheckBox cb = new JCheckBox(categories.get(category)); cb.addActionListener(e -> { @@ -667,7 +682,7 @@ private Future> askForCategories(String forWhat, Map> askForCategories(String forWhat, Map(); + } else { + lastSelectedCategoriesList.clear(); + } + chosenCategories.forEach(cat -> lastSelectedCategoriesList.putIfAbsent(cat, categories.get(cat))); }); cancelButton.addActionListener(e -> { future.completeExceptionally(new RuntimeException("User cancelled")); @@ -750,16 +772,16 @@ private Future> askForCategories(String forWhat, Map validCategories = null; try { - validCategories = askForCategories("send").get(); + validCategories = isAskForCategories ? askForCategories("send", touchedCategoriesList).get() : null; } catch (Exception e) { return; } - Set sentProps = new LinkedHashSet(); + Set sentProps = new LinkedHashSet<>(); ArrayList sysPropToSend = new ArrayList<>(); for (SystemProperty sp : params.values()) { - if (!validCategories.contains(sp.getCategoryId())) + if (validCategories != null && !validCategories.contains(sp.getCategoryId())) continue; // Skip if not in the list of valid categories if (sp.getTimeDirty() > sp.getTimeSync()) { // sendProperty(sp); @@ -769,6 +791,9 @@ private void sendPropertiesToSystem() { } if (!sysPropToSend.isEmpty()) { boolean ret = sendProperty(sysPropToSend.toArray(new SystemProperty[0])); + if (ret) { + touchedCategoriesList.clear(); + } if (!ret) { return; @@ -789,9 +814,9 @@ private void sendPropertiesToSystem() { } private void savePropertiesToSystem() { - List validCategories = null; + List validCategories; try { - validCategories = askForCategories("save").get(); + validCategories = isAskForCategories ? askForCategories("save").get() : null; } catch (Exception e) { return; @@ -801,7 +826,7 @@ private void savePropertiesToSystem() { ArrayList secNames = new ArrayList<>(); for (SystemProperty sp : propsInPanel) { String sectionName = sp.getCategoryId(); - if (!validCategories.contains(sectionName)) + if (validCategories != null && !validCategories.contains(sectionName)) continue; // Skip if not in the list of valid categories if (!secNames.contains(sectionName)) secNames.add(sectionName); From 601d959aa48f461c59b07245f4b3eec9300da30c Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 7 Jan 2025 10:51:27 +0000 Subject: [PATCH 77/92] Updated copy years. --- .../pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java | 2 +- src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java | 2 +- src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java | 2 +- .../pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java | 2 +- .../neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java | 2 +- .../neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java index 6b604e3d4d..bce18d2400 100644 --- a/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java +++ b/plugins-dev/caravel-env/src/java/pt/lsts/neptus/plugins/caravelenv/CaravelDataPlotter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Copyright (c) 2004-2025 Universidade do Porto - Faculdade de Engenharia * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) * All rights reserved. * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal diff --git a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java index 676af2ce91..bf741a5e39 100644 --- a/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java +++ b/src/java/pt/lsts/neptus/comm/admin/CommsAdmin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Copyright (c) 2004-2025 Universidade do Porto - Faculdade de Engenharia * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) * All rights reserved. * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal diff --git a/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java b/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java index 81f2903e91..90681429ef 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/ImcFullIridiumMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Copyright (c) 2004-2025 Universidade do Porto - Faculdade de Engenharia * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) * All rights reserved. * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal diff --git a/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java b/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java index fc4c035390..51ae4c1b1e 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java +++ b/src/java/pt/lsts/neptus/comm/iridium/UpdateDeviceActivation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Copyright (c) 2004-2025 Universidade do Porto - Faculdade de Engenharia * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) * All rights reserved. * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java index 80b744a5c6..4ba7404ab1 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerAnnounceProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Copyright (c) 2004-2025 Universidade do Porto - Faculdade de Engenharia * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) * All rights reserved. * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java index e6a389258c..6c2c98eda4 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcMsgManagerMessageProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2024 Universidade do Porto - Faculdade de Engenharia + * Copyright (c) 2004-2025 Universidade do Porto - Faculdade de Engenharia * Laboratório de Sistemas e Tecnologia Subaquática (LSTS) * All rights reserved. * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal From 2dcdb0a51d7d64f0e1ebfa35f81ebf7a604f4c21 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Tue, 7 Jan 2025 13:52:32 +0000 Subject: [PATCH 78/92] plugins/sunfish/IridiumComms: Updated logo for small size better visibility. --- .../neptus/plugins/sunfish/IridiumComms.java | 2 +- .../images/iridium/iridium-logo-alt.png | Bin 0 -> 21160 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/resources/images/iridium/iridium-logo-alt.png diff --git a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java index 55ce279305..e0fbb6d62c 100644 --- a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java +++ b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java @@ -87,7 +87,7 @@ * @author zp * */ -@PluginDescription(name = "Iridium Communications Plug-in", icon = "images/iridium/iridium-logo.png") +@PluginDescription(name = "Iridium Communications Plug-in", icon = "images/iridium/iridium-logo-alt.png") @SuppressWarnings("unused") public class IridiumComms extends SimpleRendererInteraction { diff --git a/src/resources/images/iridium/iridium-logo-alt.png b/src/resources/images/iridium/iridium-logo-alt.png new file mode 100644 index 0000000000000000000000000000000000000000..07a7a4ceec2c79ac25bd5990b00253edb3c7da70 GIT binary patch literal 21160 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
8rk-^#>N%Js_&kXpmE&H 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 Date: Thu, 9 Jan 2025 16:33:43 +0000 Subject: [PATCH 79/92] comm/iridium/HubIridiumMessenger: Fix to not send IMEI if is empty. --- src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java index 752098bdcd..27451d2388 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java @@ -199,7 +199,8 @@ public void sendMessageRaw(String destinationName, String imeiAddr, byte[] data) conn.setRequestProperty( "source", GeneralPreferences.imcCcuName.toLowerCase(Locale.ROOT)); conn.setRequestProperty( "destination", destinationName); - conn.setRequestProperty( "imei", imeiAddr); + if (imeiAddr != null && !imeiAddr.isEmpty()) + conn.setRequestProperty( "imei", imeiAddr); conn.setRequestProperty( "Content-Length", String.valueOf(data.length * 2) ); From 788123bce59c0c7f177a34793108a6858558653c Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 9 Jan 2025 16:49:40 +0000 Subject: [PATCH 80/92] comm/iridium/HubIridiumMessenger: Fix to not send IMEI if is trimmed empty. --- src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java index 27451d2388..0290faabd8 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java @@ -199,7 +199,7 @@ public void sendMessageRaw(String destinationName, String imeiAddr, byte[] data) conn.setRequestProperty( "source", GeneralPreferences.imcCcuName.toLowerCase(Locale.ROOT)); conn.setRequestProperty( "destination", destinationName); - if (imeiAddr != null && !imeiAddr.isEmpty()) + if (imeiAddr != null && !imeiAddr.trim().isEmpty()) conn.setRequestProperty( "imei", imeiAddr); conn.setRequestProperty( "Content-Length", String.valueOf(data.length * 2) ); From 09fec55addc4a1199d81bcc10f1ac54df5a83943 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 9 Jan 2025 16:43:10 +0000 Subject: [PATCH 81/92] comm/iridium/RockBlockIridiumMessenger: Fix to not send IMEI if is trimmed empty. --- .../pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java index 4ac4a4433a..7971cb5457 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java @@ -232,7 +232,7 @@ public void sendMessage(IridiumMessage msg) throws Exception { @Override public void sendMessageRaw(String destinationName, String imeiAddr, byte[] data) throws Exception { - if (imeiAddr == null || imeiAddr.isEmpty()) { + if (imeiAddr == null || imeiAddr.trim().isEmpty()) { VehicleType vt = VehiclesHolder.getVehicleById(destinationName); if (vt == null) { throw new Exception("Cannot send message to an unknown destination"); From 50af48abfdde707ce17beb859f38f5cea44d9650 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 15 Jan 2025 10:43:40 +0000 Subject: [PATCH 82/92] plugins/sunfish/IridiumComms: Updated logo. --- .../src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java index e0fbb6d62c..55ce279305 100644 --- a/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java +++ b/plugins-dev/sunfish/src/java/pt/lsts/neptus/plugins/sunfish/IridiumComms.java @@ -87,7 +87,7 @@ * @author zp * */ -@PluginDescription(name = "Iridium Communications Plug-in", icon = "images/iridium/iridium-logo-alt.png") +@PluginDescription(name = "Iridium Communications Plug-in", icon = "images/iridium/iridium-logo.png") @SuppressWarnings("unused") public class IridiumComms extends SimpleRendererInteraction { From ede121715970f4e25e1cd12042d265bac3be4d77 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Wed, 15 Jan 2025 17:27:56 +0000 Subject: [PATCH 83/92] types/comm/protocol/IridiumArgs: Allowing 2 imei for Iridium. Also switches the active one dependent of the received msgs. --- .../comm/iridium/HubIridiumMessenger.java | 19 +++++- .../neptus/comm/iridium/IridiumManager.java | 3 +- .../iridium/RockBlockIridiumMessenger.java | 10 ++- .../types/comm/protocol/IridiumArgs.java | 68 ++++++++++++++++++- .../neptus/types/vehicle/VehiclesHolder.java | 2 +- 5 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java index 0290faabd8..7833f4a924 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/HubIridiumMessenger.java @@ -40,6 +40,9 @@ import pt.lsts.neptus.comm.manager.imc.ImcId16; import pt.lsts.neptus.comm.manager.imc.ImcSystem; import pt.lsts.neptus.comm.manager.imc.ImcSystemsHolder; +import pt.lsts.neptus.types.comm.CommMean; +import pt.lsts.neptus.types.comm.protocol.IridiumArgs; +import pt.lsts.neptus.types.comm.protocol.ProtocolArgs; import pt.lsts.neptus.types.coord.LocationType; import pt.lsts.neptus.types.vehicle.VehicleType; import pt.lsts.neptus.types.vehicle.VehiclesHolder; @@ -267,6 +270,7 @@ public Collection pollMessages(Date timeSince) throws Exception for (HubMessage m : msgs) { try { ret.add(m.message()); + updateVehicleWithLastSeenImei(m.imei, m.createdAt()); } catch (Exception e) { String report = new String(Hex.decodeHex(m.msg.toCharArray())); @@ -284,11 +288,12 @@ public Collection pollMessages(Date timeSince) throws Exception long timestamp = parseTimeString(timeOfDay).getTime(); ImcSystem system = ImcSystemsHolder.getSystemWithName(vehicle); - + if (system != null) { system.setLocation(new LocationType(lat, lon), timestamp); } + updateVehicleWithLastSeenImei(m.imei, m.createdAt() != null ? m.createdAt() : m.updatedAt()); NeptusLog.pub().info("Text report: {}", report); } @@ -300,7 +305,17 @@ public Collection pollMessages(Date timeSince) throws Exception return ret; } - + + public static void updateVehicleWithLastSeenImei(String imei, Date date) { + VehicleType veh = VehiclesHolder.getVehicleWithImei(imei); + if (veh != null) { + IridiumArgs iridiumArgs = (IridiumArgs) veh.getProtocolsArgs().get(CommMean.IRIDIUM); + if (iridiumArgs != null) { + iridiumArgs.setLastSeenImei(imei, date); + } + } + } + public static Date parseTimeString(String timeOfDay) { GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("UTC")); String[] timeParts = timeOfDay.split(":"); diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java index 3c0ccd6fe7..5b51c67543 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java @@ -122,8 +122,9 @@ public IridiumMessenger getCurrentMessenger() { } private final Runnable pollMessages = new Runnable() { - Date lastTime = new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); + //Date lastTime = new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); //Date lastTime = new GregorianCalendar(2024, Calendar.NOVEMBER, 6).getTime(); // new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); + Date lastTime = new GregorianCalendar(2025, Calendar.JANUARY, 14).getTime(); // new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); @Override public void run() { diff --git a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java index 7971cb5457..b12f973db9 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java @@ -85,6 +85,8 @@ import pt.lsts.neptus.util.conf.ConfigFetch; import pt.lsts.neptus.util.http.client.HttpClientConnectionHelper; +import static pt.lsts.neptus.comm.iridium.HubIridiumMessenger.updateVehicleWithLastSeenImei; + /** * This class uses the RockBlock HTTP API (directly) to send messages to Iridium destinations and a gmail inbox to poll * for incoming messages @@ -225,7 +227,7 @@ public void sendMessage(IridiumMessage msg) throws Exception { if (askCredentials()) return; - String result = sendToRockBlockHttp(args.getImei(), getRockBlockUsername(), getRockBlockPassword(), + String result = sendToRockBlockHttp(args.getLastSeenImei(), getRockBlockUsername(), getRockBlockPassword(), msg.serialize()); checkResponseFromServer(result); } @@ -238,7 +240,7 @@ public void sendMessageRaw(String destinationName, String imeiAddr, byte[] data) throw new Exception("Cannot send message to an unknown destination"); } IridiumArgs args = (IridiumArgs) vt.getProtocolsArgs().get("iridium"); - imeiAddr = args.getImei(); + imeiAddr = args.getLastSeenImei(); } if (askCredentials()) @@ -326,7 +328,8 @@ else if (m.getContent() instanceof MimeMultipart) { if (matcher.matches()) { InputStream stream = (InputStream) p.getContent(); byte[] data = IOUtils.toByteArray(stream); - IridiumMessage msg = process(data, matcher.group(1), matcher.group(2), m.getSentDate()); + IridiumMessage msg = process(data, matcher.group(1), matcher.group(2), + m.getSentDate() == null ? m.getReceivedDate() : m.getSentDate()); if (msg != null) messages.add(msg); } @@ -363,6 +366,7 @@ private IridiumMessage process(byte[] data, String fromImei, String seqNumber, D if (irMsg.source == ImcId16.NULL_ID.intValue()) { // Let us try to fill the source from imei irMsg.source = HubIridiumMessenger.HubMessage.findSystemIdByImei(fromImei); + updateVehicleWithLastSeenImei(fromImei, sentDate); } // If not set, set the timestamp diff --git a/src/java/pt/lsts/neptus/types/comm/protocol/IridiumArgs.java b/src/java/pt/lsts/neptus/types/comm/protocol/IridiumArgs.java index e338c733bd..95bf4fdb77 100644 --- a/src/java/pt/lsts/neptus/types/comm/protocol/IridiumArgs.java +++ b/src/java/pt/lsts/neptus/types/comm/protocol/IridiumArgs.java @@ -39,10 +39,13 @@ import com.l2fprod.common.propertysheet.DefaultProperty; import com.l2fprod.common.propertysheet.Property; +import org.dom4j.Node; import pt.lsts.neptus.gui.PropertiesProvider; import pt.lsts.neptus.plugins.NeptusProperty; import pt.lsts.neptus.plugins.PluginUtils; +import java.util.Date; + /** * @author zp * @@ -51,13 +54,20 @@ public class IridiumArgs extends ProtocolArgs implements PropertiesProvider { @NeptusProperty private String imei = ""; - + @NeptusProperty + private String imei1 = ""; + + private int lastActiveImei = 0; + private Date lastImeiDateReceived = new Date(0); + @Override public Document asDocument(String rootElementName) { Document document = DocumentHelper.createDocument(); Element root = document.addElement(rootElementName); if (!imei.isEmpty()) root.addElement("imei", imei); + if (!imei1.isEmpty()) + root.addElement("imei1", imei1); return document; } @@ -65,7 +75,9 @@ public Document asDocument(String rootElementName) { public boolean load(Element elem) { try { imei = elem.selectSingleNode("//imei").getText(); - return true; + Node imei1Elem = elem.selectSingleNode("//imei1"); + imei1 = imei1Elem != null ? imei1Elem.getText() : ""; + return true; } catch (Exception e) { e.printStackTrace(); @@ -73,6 +85,48 @@ public boolean load(Element elem) { } } + public boolean setLastSeenImei(int imei, Date date) { + if (!lastImeiDateReceived.before(date)) + return false; + int oldImei = lastActiveImei; + if (imei == 0) + lastActiveImei = 0; + else if (imei == 1) + lastActiveImei = 1; + else + return false; + if (oldImei != lastActiveImei) + System.out.println("Switched to IMEI " + getLastSeenImei()); + lastImeiDateReceived = date; + return true; + } + + public boolean setLastSeenImei(String imei, Date date) { + if (!lastImeiDateReceived.before(date)) + return false; + int oldImei = lastActiveImei; + if (imei == null || imei.isEmpty()) + return false; + if (imei.equals(this.imei)) + lastActiveImei = 0; + else if (imei.equals(this.imei1)) + lastActiveImei = 1; + else + return false; + if (oldImei != lastActiveImei) + System.out.println("Switched to IMEI " + getLastSeenImei()); + lastImeiDateReceived = date; + return true; + } + + public String getLastSeenImei() { + if (lastActiveImei == 0) + return imei; + else if (lastActiveImei == 1) + return imei1; + return ""; + } + /** * @return the imei */ @@ -86,7 +140,15 @@ public String getImei() { public void setImei(String imei) { this.imei = imei; } - + + public String getImei1() { + return imei1; + } + + public void setImei1(String imei1) { + this.imei1 = imei1; + } + @Override public DefaultProperty[] getProperties() { return PluginUtils.getPluginProperties(this); diff --git a/src/java/pt/lsts/neptus/types/vehicle/VehiclesHolder.java b/src/java/pt/lsts/neptus/types/vehicle/VehiclesHolder.java index 0e554c1c12..bd791c4a92 100644 --- a/src/java/pt/lsts/neptus/types/vehicle/VehiclesHolder.java +++ b/src/java/pt/lsts/neptus/types/vehicle/VehiclesHolder.java @@ -185,7 +185,7 @@ public static VehicleType getVehicleWithImei(String imei) { return vtList.stream().filter(vt -> vt.getProtocolsArgs().containsKey(CommMean.IRIDIUM)).filter(vt -> { IridiumArgs args = (IridiumArgs) vt.getProtocolsArgs().get(CommMean.IRIDIUM); - return args.getImei().equals(imei); + return args.getImei().equals(imei) || (args.getImei1() != null && args.getImei1().equals(imei)); }).findFirst().orElse(null); } From 827425f785915dc08ad8e533a770b876744b6e94 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Thu, 16 Jan 2025 12:50:50 +0000 Subject: [PATCH 84/92] comm/iridium/IridiumManager: Fix hard coded change for test. --- src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java index 5b51c67543..3c0ccd6fe7 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumManager.java @@ -122,9 +122,8 @@ public IridiumMessenger getCurrentMessenger() { } private final Runnable pollMessages = new Runnable() { - //Date lastTime = new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); + Date lastTime = new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); //Date lastTime = new GregorianCalendar(2024, Calendar.NOVEMBER, 6).getTime(); // new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); - Date lastTime = new GregorianCalendar(2025, Calendar.JANUARY, 14).getTime(); // new Date(System.currentTimeMillis() - Duration.ofHours(1).toMillis()); @Override public void run() { From b09e4f3fa9f25de905048cb43857e52e72d9d739 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 17 Jan 2025 09:11:28 +0000 Subject: [PATCH 85/92] comm/iridium/RockBlockIridiumMessenger: Cleanup. --- .../lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java index b12f973db9..0d85e39a12 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java @@ -328,7 +328,9 @@ else if (m.getContent() instanceof MimeMultipart) { if (matcher.matches()) { InputStream stream = (InputStream) p.getContent(); byte[] data = IOUtils.toByteArray(stream); - IridiumMessage msg = process(data, matcher.group(1), matcher.group(2), + String fromImei = matcher.group(1); + String seqNumber = matcher.group(2); + IridiumMessage msg = process(data, fromImei, seqNumber, m.getSentDate() == null ? m.getReceivedDate() : m.getSentDate()); if (msg != null) messages.add(msg); From 07943d73e27ce25595ec692aca138111f2896f09 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 17 Jan 2025 09:12:05 +0000 Subject: [PATCH 86/92] comm/iridium/RockBlockIridiumMessenger: Fix last seen IMEI update to vehicle. --- .../pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java index 0d85e39a12..7b12b373ae 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java +++ b/src/java/pt/lsts/neptus/comm/iridium/RockBlockIridiumMessenger.java @@ -368,8 +368,8 @@ private IridiumMessage process(byte[] data, String fromImei, String seqNumber, D if (irMsg.source == ImcId16.NULL_ID.intValue()) { // Let us try to fill the source from imei irMsg.source = HubIridiumMessenger.HubMessage.findSystemIdByImei(fromImei); - updateVehicleWithLastSeenImei(fromImei, sentDate); } + updateVehicleWithLastSeenImei(fromImei, sentDate); // If not set, set the timestamp if (!new Date(irMsg.timestampMillis).before(now) && sentDate != null) { From 885aec3e4b2318ab6add1c53f7715fd1c01bdae7 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 17 Jan 2025 09:13:24 +0000 Subject: [PATCH 87/92] comm/iridium/IridiumMessage: This can no longer be done here or overshadow the text messages guessing of the source. --- src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java b/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java index dc340cea86..75e39ca022 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/IridiumMessage.java @@ -106,8 +106,8 @@ public static IridiumMessage deserialize(byte[] data) throws Exception { } if (m != null) { - m.setSource(mgid > -1 ? source : 0xFFFF); - m.setDestination(mgid > -1 ? dest : 0xFFFF); + //m.setSource(mgid > -1 ? source : 0xFFFF); + //m.setDestination(mgid > -1 ? dest : 0xFFFF); m.setMessageType(mgid); if (mgid > -1) m.deserializeFields(iis); From d89b6cfd23018268cd32aeac9aee8315a15394b7 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 17 Jan 2025 09:14:53 +0000 Subject: [PATCH 88/92] comm/iridium/PlainTextReportMessage: Adding process of (vehicle - xxx) text part in the text message. --- .../lsts/neptus/comm/iridium/PlainTextReportMessage.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/java/pt/lsts/neptus/comm/iridium/PlainTextReportMessage.java b/src/java/pt/lsts/neptus/comm/iridium/PlainTextReportMessage.java index 33fa60a010..a888fc9780 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/PlainTextReportMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/PlainTextReportMessage.java @@ -60,6 +60,7 @@ public class PlainTextReportMessage extends IridiumMessage { String report; String vehicle; + String vehicleAlt; String timeOfDay; int source = 0xFFFF; double latDeg; @@ -104,6 +105,7 @@ public Collection asImc() { public String toString() { return "Report: " + report + "\n" + "Vehicle: " + vehicle + "\n" + + "Vehicle Alt: " + (vehicleAlt == null ? "" : vehicleAlt) + "\n" + "Time of day: " + timeOfDay + "\n" + "Lat: " + latDeg + "\n" + "Lon: " + lonDeg + "\n" @@ -124,6 +126,11 @@ private void parse() throws Exception { } vehicle = matcher.group(2); + String[] tks = vehicle.split(" - "); + if (tks.length > 1) { + vehicleAlt = vehicle.replaceFirst(tks[0], "").trim(); + vehicle = tks[0]; + } timeOfDay = matcher.group(3); String latMins = matcher.group(4); String lonMins = matcher.group(5); From d3b5eb00d2b4e5f59f82294fb1cf7914d0c175f0 Mon Sep 17 00:00:00 2001 From: Paulo Dias Date: Fri, 17 Jan 2025 09:15:14 +0000 Subject: [PATCH 89/92] comm/iridium/PlainTextReportMessage: Adding process of (vehicle - xxx) text part in the text message. --- .../neptus/comm/iridium/PlainTextMessage.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/java/pt/lsts/neptus/comm/iridium/PlainTextMessage.java b/src/java/pt/lsts/neptus/comm/iridium/PlainTextMessage.java index 93545a2d9c..2367e053db 100644 --- a/src/java/pt/lsts/neptus/comm/iridium/PlainTextMessage.java +++ b/src/java/pt/lsts/neptus/comm/iridium/PlainTextMessage.java @@ -32,27 +32,35 @@ */ package pt.lsts.neptus.comm.iridium; +import pt.lsts.imc.IMCDefinition; import pt.lsts.imc.IMCInputStream; import pt.lsts.imc.IMCMessage; import pt.lsts.imc.IMCOutputStream; import pt.lsts.imc.TextMessage; import pt.lsts.neptus.NeptusLog; +import javax.xml.bind.annotation.adapters.HexBinaryAdapter; +import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author pdias * */ public class PlainTextMessage extends IridiumMessage { + private static final Pattern p0 = Pattern.compile("\\(([^\\)]*)\\).*"); String text; byte[] rawData; + public String vehicle = ""; + public PlainTextMessage() { super(-1); } @@ -73,6 +81,17 @@ public int deserializeFields(IMCInputStream in) throws Exception { rawData = data; text = new String(data, StandardCharsets.UTF_8); text = text.trim(); + + Matcher matcher = p0.matcher(text); + if (matcher.matches()) { + vehicle = matcher.group(1).trim(); + String[] tks = vehicle.split(" - "); + if (tks.length > 1) { + vehicle = tks[0]; + } + source = IMCDefinition.getInstance().getResolver().resolve(vehicle); + } + return text.getBytes(StandardCharsets.UTF_8).length; } @@ -125,4 +144,23 @@ static IridiumMessage createTextMessageFrom(IMCInputStream in) throws Exception plainTextMessage.deserializeFields(in); return plainTextMessage; } + + public static void main(String[] args) { + String textMsg = "(caravel) 2025/01/16 09:52:16 (APC):Using Modem 1"; + + byte[] bytesMsh = textMsg.getBytes(); + + IMCInputStream iis = new IMCInputStream(new ByteArrayInputStream(bytesMsh), IMCDefinition.getInstance()); + iis.setBigEndian(false); + PlainTextMessage txtIridium = new PlainTextMessage(); + try { + txtIridium.deserializeFields(iis); + NeptusLog.pub().info("Received a plain text from " + txtIridium.text); + System.out.println("Received a plain text from " + txtIridium + " :: " + txtIridium.vehicle); + } + catch (Exception e) { + NeptusLog.pub().error(e); + e.printStackTrace(); + } + } } From 598680838eee43355db4b65429bd5958faa1da56 Mon Sep 17 00:00:00 2001 From: Miguel Carvalho Date: Thu, 16 Jan 2025 13:16:01 +0000 Subject: [PATCH 90/92] swing/HoldFillButton: Added tick icon when button action is actually fired. --- .../lsts/neptus/gui/swing/HoldFillButton.java | 27 +++++++++++++----- src/resources/images/buttons/tick.png | Bin 0 -> 8263 bytes 2 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 src/resources/images/buttons/tick.png diff --git a/src/java/pt/lsts/neptus/gui/swing/HoldFillButton.java b/src/java/pt/lsts/neptus/gui/swing/HoldFillButton.java index df4b343073..90c4c67733 100644 --- a/src/java/pt/lsts/neptus/gui/swing/HoldFillButton.java +++ b/src/java/pt/lsts/neptus/gui/swing/HoldFillButton.java @@ -52,9 +52,12 @@ public class HoldFillButton extends JButton { private Timer timer; private int progress = 0; - private int holdDurationMs = 2000; // 2 seconds + private int holdDurationMillis = 2000; + private final Color fillColor = new Color(0, 128, 255, 100); + private final int tempButtonDurationMillis = 1000; private final List actionListeners = new ArrayList<>(); private final ImageIcon LOCK_CLOCK = new ImageIcon(ImageUtils.getScaledImage("images/buttons/lock_clock.png", 15, 15)); + private final ImageIcon TICK = new ImageIcon(ImageUtils.getScaledImage("images/buttons/tick.png", 15, 15)); public HoldFillButton(String text) { super(text); @@ -62,10 +65,10 @@ public HoldFillButton(String text) { setupButton(); } - public HoldFillButton(String text, int holdDurationMs) { + public HoldFillButton(String text, int holdDurationMillis) { super(text); setIcon(LOCK_CLOCK); - this.holdDurationMs = holdDurationMs; + this.holdDurationMillis = holdDurationMillis; setupButton(); } @@ -81,13 +84,14 @@ public void mousePressed(MouseEvent e) { timer = new Timer(10, event -> { long elapsed = System.currentTimeMillis() - pressStartTime; - progress = (int) (elapsed * 100 / holdDurationMs); + progress = (int) (elapsed * 100 / holdDurationMillis); repaint(); - if (elapsed >= holdDurationMs) { + if (elapsed >= holdDurationMillis) { timer.stop(); triggerAction(); progress = 0; + repaint(); } }); timer.start(); @@ -104,6 +108,8 @@ public void mouseReleased(MouseEvent e) { } private void triggerAction() { + progress = 0; + changeButtonTemporarily(); fireCustomActionPerformed(); } }); @@ -120,6 +126,15 @@ this, ActionEvent.ACTION_PERFORMED, getActionCommand() } } + private void changeButtonTemporarily() { + setIcon(TICK); + Timer timer = new Timer(tempButtonDurationMillis, (ActionEvent event) -> { + setIcon(LOCK_CLOCK); + }); + timer.setRepeats(false); // Run only once + timer.start(); + } + @Override public void addActionListener(ActionListener l) { if (l == null) { @@ -138,8 +153,6 @@ protected void paintComponent(Graphics g) { int fillWidth = (int) (getWidth() * (progress / 100.0)); - Color fillColor = new Color(0, 128, 255, 100); - g2d.setColor(fillColor); g2d.fillRect(0, 0, fillWidth, getHeight()); } diff --git a/src/resources/images/buttons/tick.png b/src/resources/images/buttons/tick.png new file mode 100644 index 0000000000000000000000000000000000000000..9b79a6f4c8b0ac227d6d2c940bf9952fe358bfd6 GIT binary patch literal 8263 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 literal 0 HcmV?d00001 From 7e5e14fe814734f98a3344a03695a4127b179868 Mon Sep 17 00:00:00 2001 From: Miguel Carvalho Date: Fri, 17 Jan 2025 09:23:27 +0000 Subject: [PATCH 91/92] comm/manager/imc/ImcId16: Added new compareTo method against integers. --- src/java/pt/lsts/neptus/comm/manager/imc/ImcId16.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/comm/manager/imc/ImcId16.java b/src/java/pt/lsts/neptus/comm/manager/imc/ImcId16.java index a9e32cb55e..d781c57342 100644 --- a/src/java/pt/lsts/neptus/comm/manager/imc/ImcId16.java +++ b/src/java/pt/lsts/neptus/comm/manager/imc/ImcId16.java @@ -105,10 +105,14 @@ public static boolean isValidIdForSource(long id) { @Override public int compareTo(ImcId16 o) { - //return (int) (longValue() - o.longValue()); return (longValue() < o.longValue() ? -1 : (longValue() == o.longValue() ? 0 : 1)); } + public int compareTo(int id) { + long i = id & 0xFFFF; + return (longValue() < i ? -1 : (longValue() == i ? 0 : 1)); + } + @Override public boolean equals(Object obj) { if(this == obj) From 1161d477d31df7e77aefe43abab90829f6474bb4 Mon Sep 17 00:00:00 2001 From: Miguel Carvalho Date: Fri, 17 Jan 2025 10:01:22 +0000 Subject: [PATCH 92/92] console/plugins/planning/MissionTreePanel: Added emergency_autonaut to plan names to automatically accept updates. --- .../lsts/neptus/console/plugins/planning/MissionTreePanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java index 216aabb636..41848150ff 100644 --- a/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java +++ b/src/java/pt/lsts/neptus/console/plugins/planning/MissionTreePanel.java @@ -131,7 +131,7 @@ public class MissionTreePanel extends ConsolePanel private int maxAcceptableElapsedTime = 600; @NeptusProperty(name = "Plan Names to Automatically Accept Updates", description = "Comma separated values. This upon reception of a plan " + "with the same name as the ones listed here, it will be automatically accepted the changes and replace it.") - private String planNamesToAutoAcceptUpdates = "teleoperation-mode, service_loiter"; + private String planNamesToAutoAcceptUpdates = "teleoperation-mode, service_loiter, emergency_autonaut"; private MissionTreeMouse mouseAdapter; private boolean running = false;

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%0AS8cvQ5g^uK_!j&&KnuV$WJK`dEUeaN~487GD(}f z-X$;}ola%!eQ*qE3R$>$mA9-sNSU(mKa5coDw2BSHaVXe$`H(fd@9B*W1D&ABNOqj zX6DssA@DQV3w5QySc|pSDYtzw^W-nJj5+2|s<2(7`lNukSmLDuR}RbHEHPy=32VKtqnYshnkpI7$b4oCIV=^tgMK8=AV z9?IbG)!?#hD*C5XT8GWq4LaE-1j6b(L1|E`DIS0jXt$0;b9%4shj7b>bRDw<&L>NJ zxr`d!?cvV!UN`W#CXi!=v=DtiGAISukxN{WDyQw;2U8bfL1fQLq}^fsoXk=TM{kn31cmhKnf*J|&VfT9d2 z7z{KJ5EK*;bC|tW+SU~+DcJw1R?uryY!NVNEm)=2$xDn#*#9I>3wkr;e{!)Ko&SFl zeHa}P;y;&a61@THKe@Ar&JO>d>{r5Y_@65;gtY_rpNqAR-upjSOaxO4>_1nU8}k(k z{{J>Ej8qNAga87XOG_xnM{Dhsz-0d4E?wW43JCuVzY0OW{@={)Nc38s1_8nPHyjTkI_K^43maU`O!y@Yk~RlTx~WQIC!TJ& zVRs^)sL7(CmZ?BW2TwRqiJ{DHH06tQG?l0Ktt^uUYc}M(`byE`}}pAc~*UOvXMP zIGX8l7*tY#0Mk8$JBlC*t}Jk~phS-pBGoGB6#o-xX?9ShzI zNu>~K)r}z{Jsj$ExUk$~@O;P78j@t%boG%!w%{`4NTmEE_sXwBCvtlZof#=ne=qaq%27qR)~um*F5+}?v; z0=WiH;-u_dKpokLe}NDo+Rk!gKKP24*XQ>h+5j(=gFp~GxUuW`fDJ;C#``*v!$>t$y@}L|V`dI8SdECt<7?97R}s z>_<_NP%B`A=LHxNEA6@GHYaBN%+;OAFz9A-UktN!iLl|20QXtqaEE%TdUT|_sBz!$ zt#a3_XfkcPSJ%zRpTV-8z;MTx>+HVX=wcM`6}2;uby^PK28je22|~cld5!)1CUQGU zFjeP$UkWNpvdqql`~2+$eZ9xWbCc_4&>!55UJT-fuc!Yc?}#CY*JsCe6UR8pcW_g+ zf0v%lbfM?7D{v9>vTn#p!lEDRg^y*nHGGc@H;1G@ILpW=;am9o$7ZXut&NxPHOw4f zD-L9U2mp%It1Du75}?>XoVD2KYuq2k4UT>yT5(xJto6S81hJGuSrl`M7Icao0h_Ua z0R=rC9SL67x?RrysdRT+8f+B_ei8vJS%Y$XklM_hiu}xlI5KjHViA@=)*TAqENm11 zZv2M6BmnG6Jc*ga$152~qR!u)HRl5a48Grbcb^AOXV>%7Uly7E?)~6v{3ZN;f|Hvg zY;n)C75GTK{gmh{cRWxq?AHePg;n~T&hw^s!PXc>r1>c) zhY-$E+zqXvkIkrYo1WN zxe0m^BD0i^0@=eC-Ic;`f$;&O-X0gPeZ^Z`J2Cxq-^nF4z`c-gjk=SW)WO?q;C>1& z9FOGb?S~dPW%a-MrK6HKr3db}yO4*dnQ%=3!->y^?@E*e^1n1X2#LFV}WtPR8;J5fP@2J(1P|R$_f1* zV{MOJfXY_%g8n|jE7`-)6IaB(`jX>q7qUnqQWGci-2%!Mt=pbQgL8|HwHLGo#s_&K z{hf^w;$ZJE6jbGNs;GT;8wif|mF=6I)jK`NN!6CArAxjC?eJ6rV$#d&)ztiWTtt5c zl8S-GsHw`vz_)a|to97Z?jFZb=+ij4$#~EJwkDFztQX^kJs}XX4yy7>3gO2M1gkHn z0>$cSix@zVM*}KaObxOoa8^Jrg*OF(B1$>xA&#d3Szq3*M}~95Khh{?qx4A#=$&C$ zB=ZY%$>;(l^byxvM}MY;!toOK=b|;a`K{E~zsi|60cKiACcq2Ge7~X^hY?N0TP_@< zVD2H440VHQEGH@_o?@Q8;jDf8e9=m!a6glrX(W-HgC1(dqXZ$NRK-wYG1FlB?i>i- zGpWMgLmtzSdNc+9TaSv=f<_dGMH)%@C3O48d&7iL(>fKBhbVzxO2>Nl!kS*Y&qI6d z)={5oM)$|=`icqgRWku=Lzz+yd|>8d+tgmkQHQqPPb5>z^J^_E(VnS*&8t_Ru+~WmdRK{rg;>*u%wLL+%};A<`k6~XN!kD=or=oS!QiBf9(A)n>__iZBYV$h7Je<{>h+bMofl7xBi53nHnkaHgC|gqd1zpX~ z(`RqztJHKq?GV{yT&r%ltsejwW9%`c%?dQxw1T}rrYS~8W7mg0PT*Zg|Dc>Zb*!R?_CMR>U4yL| zfNvqj!`on0R%rtfwOYxc+Z4$~4o{MZ}R_qV$zqtL;l*f&PDnO>>ljMPVl~nMWx@HIrnnqaokwqiZ!#6+Hsg*?oAjDFjL_$)PaoUfKhKEI(_& zrxJ(I6n$?z^TckU>j+k+D2QMVC}RM@>wTzm9_~!ifl?MJ-+x(y{P_??HN2jl89v`L zE^(JU^3mqz_Ymhy?p|I?plt8cMD^3LB{2gIMI14VVdv~Oy({B>J>+t+HKBvr+uj4M zAU^Q64XSd6Z3)GNxfc@_gyGr9APVw94!gJ}*IpQ+~b;%7Jy>JvPQv5&M7JlxVAO$vR z>WGY%jb4%q?T&SaE$!2+jX)u!D?LWTjtWA7Y(p4xAr=!lwiF7VaE`O^{?M~wnCkG} zdoQ!HPe(l!X=ta(H%@M=!|VcVy`SD5MtuWHOHr_y0y14XW2qQ{eq$D{fu95u0hNkH zNWm4uxkp)S?sNCVC`)^1k0nD+1@r}5k%Y`HqN?TH_-2z0U@A0R;Vbweu^GS-8<8yh zKd#;}y0Yg97mjV)$;7rMm^hi(wmGp*Y}>YN+qSKVGf5_X^Z!lmy6e8*YSpf)?%li3 z>B7_9pV`BT@8GaWdE}&KiW5T4BYdb)+PMn!#E=)uT6|1y$^9JUc>|uJijv2GQ*EL| zXNfvXRD!t~a5yM^6yGATQSim?u?}jqj4JVKHHcSs@gAPu5sE?GYLX!Lk!JjfMiHw} zP(xVB;9y*Iw?74R&o-{Ohi(y3mq~}BbVtP3pb3Jll)SOUNCSAL!}h>KyFV=uazO;e z?9k(UK5kXH4yG#xvzFTD9QKm{jh#cxmMPWd9{YP(yow2LJcm5AF1#&`AdUX&E|)#n zTaYp`G;@(XG0s~3_oYsi&&H2penb+0T6zJ|^J?o0N!f8nHZ=MTh)TQPEyFpqa+~iJ z$KhTYdxZ?j3Ebav^T2ZdZpN{-hEiN5n9oe9_`h(EgYK-KYeSt$t;AUXY=-r+<0B$} zR!Ac@iP(KZQIi@3j#YR|m{ojhbgDE^udl8RA(`~%KMEb}3IojkCg{e`g5QeC&!4dz zuL;c}Qi}!=m)3lJrYYy=bLM}$ftK&NF}WIzJCWe5;Kr9z9N_1X&C3xWr?rl567SOC zBsr$cH@m49I!ZBcBqrttgauLXy5*%d8Xip4G>+&CNde98ciV9~SH*H5`4D#v%e(Q9 zSl%59Vv|-YAH*kNIA>*%$bXZ#^b;CAk}p#$UpO|r6!3k<>+>k&>J1fclrs?^KBsIv zHM~$#ZpY$(@xt$}ob>FjoVNdH7^iiN`<1NpG8|N(y~96DI|qUZNWC6`J{qXQh$O>& z*@HczXcG~fXRF+OcKbWKEeo&C1EqY+*%tZtC&V=L8GJ&TWgs;7EhRLPOiNaYRKJs= zQ)2-h@eEVbxr_Vrv8;tU-jN<#4It-{=&rM_BN&tdp_(e>a%Tm7Y4i#@H@ zO=1+-Y2|E}ll6WT0CZz;VLRuCHC_=5-b0XJ0>MfTWmeqhuvCEzbJ4t+Q`0*3OXVt1 zGTpvET0NOzJF`h+4W&1(J#-o%kpl{($_KzUU^0$=x-{}*fk4g(`eKlt+?s(6zG5h0_Hmv z&{NKXHsBo7oih)(^x9AAmCYXVLe1uZ8n)k@l#MZDS1&cvq$0|^0q1V;Yf|)?>=cW; z!8+vh=z@&fe|u=JP~`h6GdvA0Csr!Sjut}VqKfJg0rshX@%ym`u1Tot4w9}XpQ2Z` zBgwa2+@WaQ@|)FWZ-s14m2oYsMl%!rN&WCww`)OFe0FT=NK{viThUcnCfHNjLYu^z zBO2jd~m*^8U)9;b3NxRMGrGL=IJ8@!C{Ta8jKYT>T-MP0iF*V-W$&*zhv_nvd z1%TIiM%!oaPwTE^61Eh(DvjP6zB>=#T>NPA3K>?`$)F5s74NhrUkW)kk65R*erfsc z6=%v~Ych0dF0!O6qGme07gtP7)g1?Ep@0}_((SQUkZuG7L`8tzEA4G=VQ&iUp|xocmo#1+XVwn}}(%rWUICfzXC zqQp7N#IuIc8wwiaTi3lILsKR1)E49wNVVfS*DQvHPdVB3;^yz%QVLQODp?U}FXu&w zgSmD`v^XHupZ8>*L1usB#;KyW3bj8cW&+Fjw>a7!3E2VTXN;56p3~$VI^)VRiM)fVfSXR-w|%Z|YId zro6pjexs;Uxk7P-GHhY0huKaOHO5sDOv$Sik#zNARJ1qaOU~m?FBe5rjNoSR zlwvo+$AG113FSJLY)^vdmhu+*;1=lj=3UhH7lvKs=sG*g0cMEooN3THNei<=%6evT zqplIoPFwyDk=0P zS>U4rd#5QuGzFy*GFQR6AOJ@{I;f+a%6zv#xgDA_=L&Gme`Z}5+i=UUxXT_dd5<_K zUyy^-_1Dj3akE_@KJVY;JT|#FZ(L<@g{_viEFbx4NG1K*`#4pa7FDElU7dyClca~a zBxrLl3LPVw%M;hQ5crtz?#0PNNP=^!5h@Y>mc<_m1Gy*+BnCD>qX=Lx)Pqqd(P>fr z#{9ORoR!~aV=d?5iTbl3M~Q*oslfCQypUf{!5~biVvq{E3r$M_GUFC6FKiuedL-%k zF1)M@xfgHld4+xY(%x+@aF01x3l$wfh^RCHK8bP$n_&twt)qL~*^bCiUr$P|T7geu ziLGpV5oSfHONmd?kQZQFxjjxzER4Aq?e|&z6Zgue*p$ztUWD~wg~uRZhZDI;Zb#A5 z=ticX_w#$Z)kZ14S^>mFXzhfC@(42Djq1F_TZ4`Uq|$NDR`BcbK4iVkLWaF~R3f~X zxIC(}Nj|gaj0(TtA+3|_9);s^qN96v8l`7Lbd1##Wq@@!#Q?~Tg1Qo?p(&7VOY|Ty zg^=~-2BrEfV=}%!Py7`u9YiSa9NGByh3i~ zvI7Vg=)rIW?Bc8kdXE>E8Rx8HXiE;RD7v~rZ-1g=ITw@CyEt&xWSb8Z3E*|!iGcQ$ zxW)o)HrHoFQUk1W&1YkI>NwQpZ|%H)4pRc;P3Y3WMn`63g!G=CRNP1EF@hL;jwPq% zQwmx1wp@Kyxo=QiASaTuD8mK|@>^8>5(#s2UnAKO2c~s?J9v_95PGRYz!q2k9G(&R z9+#=4Fz4#D!E>sEFciRh{|DAE;Fc6p7Sg$dHoOSzLk)0@B7fi8Uo0EwPE38WCoM}& zy)d1VYelfrtE&Do+r-+&+A2$CV@7&eOmxtWHuPHPSesrrius4SKb2lM_l-+ zsp*8riXx#BX4#}XOrX#P;}ASCY>uI;#?)z~>qx2RjX;p1OT@dx+eMi&%Ju{dwD(pz zq;92#YY$)+#pM{9_Y-6f``5wmGB2I+07T{_s0;?8nW~y@d ze@sU=k8jx6f!hpMRL|wEpD!7@%Af?O1Th}$L^QB+NnwMKgfhP-QK{=ypiLQ$fc1WPK zNt*%kbhoruZJnm{1!p&|g57Pbyd!Cq{!X;3qG)G$6}p+V8NN{uQctQb^fd<{t!3PQC>t)5ZGcd!m$_m)dbYLqC zGF`aPzW#J+R~E~xzdsL?h{N2pbf%IiN7V_W_r(y(%Ns&t$!Cuvmv#tbs30f$2b}}d zh#6R&pc8nP*(+dw*O{LEy>vD z(}suKak~V91XeE{trJn>-l#l+C#mfW7SmG%ssoA^h~=epoo@tRRI!sfOx*S+eIvYk zz`eUoZ;KaB_Q}=ju=}mX-*H}Mh`0q1qYIaOOHHzkv9^-LQ3z>TCD@in1a*6|s+?o3 zn4~I{3@3Fe)7kP<(}v&(ERS1xi~JDyJc#oa#ZS}CI?N$q~`_2rjfvw zu67)GCuT8h6{Mn*Ao>BN*?|qalLvKo z*ZfQXNZ^YAqXklBJ4RVx>XFhDx&p=N0XCG~-H&JHXa2U(Z=q{M$LS#{?Q_Lef7tYR ztuX@la;f6$EbLWmtS8AK;vjH@R3Rdf)gHehqZ{ zDJ=bUW;mA*N-Q@ll(S0^5UGbZ{yR@=S8JwM0ys+xBh62SOh=H^aU|E0IMK*gl@;|o0HPT zfj(8Caq@VL*Q-cZjoyTqo^q`+mg5HZON$T1XIKKW3OaKKBj5gHHsiP=ofs%Pthcfc z_El6$wd&!+I!+ps+qYF`#*DS^T4?aoyX}IT-9JAQC90~aGU#hcv7<*NITxEydY?6J zIMgg9dTJt1``W{&0%Ad9?Sr^AF8RH8_Hu;9mi(;zoh0p;whqla}Nvo%VSN@G6lHMro_NXibq4WnsE@gJ}WLyPP)BfGuB!U_wMn;~-z#-6hND zNbB`sWr$_#M0(+RTmzESbIZ55Q|j?Wa?bn04lqe&Lf89r9YWPug(Mbw_j)(C;p!f@ zj)8%)pff-H7olCT2Lunae0+z?x?c{8{zaL$qK>g}W#6)^mnHqmDa{2Z)PqC6k#eym zNl$`UII#(+03h}S3SDPp%%hWa5>0e6HCwrJO0uWB3Ar73K;JbRp>EcCw>^=oz9G6p z(mkpdWVvGIyds#|gr(_}ywdKS~FP?iei0QPanqd4{v^xl42N0lZRJEV*14bpRlIS`#N+tY_ zXfadz+aQaj@Hqms(NFu!aBG2$sMNR-96a-dwjG7lQ7+NpN(_`YnfL7|6CQiY=^~Mr z)O25>E%G`#j$v>XiK~1kVX{8!(4$vEd>uj*r|24~Fe3y@d~0>22Sq^Mfz>-DL;euA z4%zK{06Mpiypf+(-=DN7Me^aQXI)wIsn}FSM#q`Jkb()I`(heu>N_j^c=Xx{yVf>0 zf0b@~q$dV5+KHxS*#EXOPMvd!byZPV7>~Rml>T;Sscyf?aAa^pdz7=`glW13Vp&jq zvQ7Z~VS~2VpRQ}32U;}G+ZS1-4q?(Ge^@@G3}8xWah9frh9sC0Z1*KSrnw zRVLS&H{Oo5xXyR@zr8270hpPz*xH=p5BsBZTWK6eUnkoI0H8P({vsD$8^Qg;2?aW` zJ6xcdTvLpjL|u(i+a~Gr@9nY5tW6Sy8pZV+o9jeB?Pgaf5YerO);c2xH|v%j1{5@R z0XoO-deCdu0~QyP=K~I~Mmrr{#LV2-@_t7J1OBrziXqjWBvP^dO4}*=sc`o?6Uhtu z0+%}>znwM`;O3_3f)_$j_!1^Y&f6`8VzG4Y=LH*Seo||CcKE0$+u_(fK~h-nqA-(l z_%A@>MQ-+MG?$qv;ilB-F(0*RrbRk_-Z#OcuejQ|Xw<*y(u?#>J9E9&Z-3Jv#pPyU zja!8BpufF)Qz`L}Q@*yw=@@j(InbL3)Uj!--QanT2G37O_{$`l|LN<&v^4R3MNxN>C>tK8u^)uzm#I5Q2>%FmW;Q)PSFr zEA8V3J!coRpNA+qX)Q+t6XGS-vc=3)v>jfxHTf~5Gml+_p|>B%J-wB8dz#qyyq+c2 zJ`rCjVsbh5BFERzzm|QX>J*Jer4`Sh%T9@>xVUUHH4x=~4vax=jGWe4@12xNe2M5RO@uC5I>-2k~I!>;C zF@`rVi(LB564riKGdo~KH5%P<-)`Ysu{vFqc}JNM$9NTlm!1~W_3!F7IvzkmcA!&2 zoV*BLw~v{dyq2^`laJ<_0`!NcKfrd*wd;e{Z?;!vsg{Ed-EbbtExU8#m2o{bEP3{>XS|*sRi>oeGyugAxu_MzIt|y>mpO##-!**pv3~@es?UQ4`||dIcnjQ z1|W%WIm*<+j;eSF zVTLp(A6gbBNOcDhE^|h>K-yV$4)p~xZuO-H{RcRYfUXq;s_{7d$72Ijy>yc4D;Iu( zx#DS_YrG)d#781YIU0o82|}1!Evk?t@MFs?Dzy=ilYu9$wr~gyK|n@k2KwX9>-pho z_+9;7J%0;eRtqEc`Bj#fj0`V@5?xn}+z!euV^oP=1k8#h`hCUoT{Dz(?&zEq+^{OZ zFS(;-e{@Q@2em;yff|E%r2zf+E;r{unRgVNfV z4z*Umc1@Hp&rf(NyiqRfTMXvyPclxqa&c@d3}z94+>fRo0(C#k3g;**Tiq)sPmc!$ z&B#YY@D*v99`B2kQli5cRjko-TP+2()`3UJKzd&&1B}II3z`-lGRPtIbGJDo2huS8 z8G`+7G+P#S^_oT@gkQHw{HQmF)JXOtO%#+cuhA??dK*E;!7*W^9C3R^rqOV8R?*TrR-J&5{)yH-vbQCe4dhb zBk_@XZdk9YPeUT~T*Je`@Br?(Gv)SBhTHgnSRdbuNV_FiQ0|OC{-2K4L225ZdhCfV zum_v0L=nD(MD&Wud3=sYD>~w#Lu0=-RzuuXy##P~o`_oU8TEhT%IUXe zs0&bV!-7HP8xq5t5;HA!-oC|BfspnB*qor+ftF1nhOkM!{-CU_b+h|p?J-9Mvxvf{ zEx<}3O%xH|cV^XcJlG=D0O8>-ib1$jWPW)NfX?Aj zrqWl(kFTwW`?Zo0C192=6)s@P6&BF=a=)yY*5M8RF?pxtay$Q%V6ae6U-OXZlo^+BounliCYO=>TZHl6-CvO0=a_^O1{h8vS&Vg_BaQ!|;GE-j+{c zv3tCDB}8jS^VEwg^eM5R&YRtaX5snv4N2r}{xgH_Jp!AH$Y8txpxfL803kjFsRe4J+0Wu)V(~$}5YhbmBBuy)f#A(N$mV~8w)Jhc zUqB?>F(y)!*58H>r#xDcm&NjEl9+!Z?~t|$gTrvu-y80*T~@B$eIc(FS6}8yE^HlE z2Cv>;^9=)6yXSpfC{n%R0a=@Wuhs7#j-J7?M%p$UB-Sb}#_kTr2V|)<_jIGWRaIwf z#;>hOU}o)9-X&j3T>LIrA9nf;%m1^j+xhc!gnssB_h09F+z`CZYTihHlNfm_=p2{U z)!l0ISM951pd<6$XUsR6VB1y2%HemHHuB+D2O2FAf<-a^ZW9Npbn7}aUYLsUHX!;B zH(eHpmr+>Yvo4BR7s=Z+)^W?=64XGxsXF*Po|QRJ#q}bJKH~&D&d~fq?oT7UoNV)k ze0lymg;bb*mk(v*au{!++4l(!T~heH;QZa`9sK`Y!kW`YFt5MBv{BQTkzb^IJ|+_U ze-K&O-gYR*&lSirxfhA#YZcRDML}*Jxxn;;0IkyjG|T+Kw1oM$h;=JsihM0?e`GL+ z!T)j3x-cuC|B*A7=mB3S-5e;4i!XuoQ}mlJZV52PpRZ1+-Jwf=fqTu9(IvkYM^93$ zDSWVoz+RPR^+${lhJSW}XE7F_|AYKKg`dBYf`2Z%Fv&N{@EFOHtfX+w3{@CR;Qu|g zp1Sqj0s;au22S2FfyYYLp(BM)HqyX2|7T})4TJZqC)nEZkDZ)N0T10AQ;%Vd|4+#!1Ecz@f$MOL zpAi2I@|$NP&%-DB`Zbx@`4gq=GX{^`Y#WCG_BE>1xfljtI)DHS>wg1Lj0lf~^3NtJ zA(rvi^U7j$^RF>$&O*Qa>fRv*ratOFSvVK;jW2;~Gz^xnp|o!%bH=c|1&HLRE~^2iWN z>`Q?0Cl>10aFu&vy?zP6>7YA<|C=m9hUj?zhNC!?4;}O0Yeg!ddq5*Ff8yMwTD2*n zKc~$gY_h!_0%o#K4k<>n6ft%xIN1LlH?x=$`9S<5rPA?8zsQ|4{Nyh(evud&@}B^j zJvP!mZj%|#7uDR#k4Fgs|36!ilqiL?pQv+|n^Ud&Rp)NjVX*|WEND^W?5Up-Y=p1P$Kd#Rn}r$e&~OF zLSVzcf%s4LY#6?H9S#VHiYA$u2@Wk;4+IYnAfLSaJC5!f610T4JXkW2b$OE(H4>hJ z+Wrnm4mtT+@F>dx^26ZVCJPY|0k?BJ^|z8+n3U7g{oh%aS-Y3kwtegwVT`STME-z+CjS-XLQUm#!FgI|JQxE(w6Bd~;$!-k|#HKI(EU?M;g}!|k zT+dfe%I9khZbMNGII;xa^FtKKAVLxnBXJZCp$%13cHq^JgFSrC#r#2HU8M>+sA5O8 zAZRJZqIA<;ge?9`$|QdvTb|4<5cF||13In%$*ol!lwm^hTg_dF%VJ7cqBioi0)Qm6 zQ=IV}D;vur>i3CANggyTE3l|)DH;xG>o@Zti;aFcIjvlE=n&U{d_N(m#jrRnpC9mC z5pue4vRL~+0`Wl;$@gEA`hI{D7%A>5uI%3W>@gMkgd3k2tLtOF{bHbn#Cw@|Gy5ac z^Qg1^uGcupo}sf_08Q8Kve-Pupap2D;jym2@|m^XH(S2YECyX3@}=wVP1I!VO)v8R zKPuMQcEqcB36ZKcB>s*z!_ih{jH0rsVmi~*cFawLc(O+CSRpko!o0ksUZo)lH=d}M z-CMY7tG!cfZ{bAy7`Dh&zd;|$BkTt8C!));5duFSu~V?yl!qe6exTHvs}c~Uubp;5 zapvRD`>N-xZATyR6OwzVbdzI-Y&@t5I_j|HhT$&JLn@C>j(L94li` zdSQd}B1M5cZL8_oWSks#ycvTe49CUM&fR1@5A!ZQ6a(jt248S*!NdjsZWwrOm$xBO zY99}NDa!|Da}npyq*NV9uOQ$8Z`lE|YIKXQ`GTFNm+6JDBI&dvFzSLa0(5vmKFl)4 z)8Nz7WbMjEzzd&kXscSiLUgY(cEO#v>U$6Ixz9D;xn&o&by>A=Ox^4z83Kd!5DkvT zq=u z3t1oIwBq*Rh*!P-aPa_5N;^x^<~R|u4yz;wFDsI64HC4}=uiTRWyrf(3VFm@ z8Z(fIUFDZU$J*?ah3YDYHn5-y-nyk)ZxZW&e#t;}=0laquzMgZ$ zsmd4l$aUh+2`?=nLDC8%V$lhDf%iP^piTcOZDAQYIhBg?S;^jkN^rjLsFIT|hgtym z(pt3+C#n<*aXLVzSRxEx>euLMGMOu7#|ie94*2rkgnJq$AKR72jrazi52&3NBM@rUa;Ip8PEW{vW}1!<3I#W9(9WHg3GR&Rrp)`&h4V%Fc3!iPo0pq)C2hIm-xayN-x|bF_6T7 z1-AvaahZZd>MlU^q5-ZS#4Gf})znnk7^4;rU3pa5FX!;`y*XkJ+h4!9af5sjy-$n* zsU04BxTsd6Ocu;-snqmE@3pP1xh3F1$StaTsE{1&c;(jIbou2M9FDK7nwU+7h;7#O z)%e#VhdKKi#YOg|__r?8=S>v|h2qwC;hTd6rN zaY=MIqgaby?yMzaEd^Bq*v9dVmK?W#vKEW7Ii?t4&3;s}Ze4fc#kZJjJsFIBmqHT_ zJ7N{-y!o70_KMSDIZ2fjRP#j#Q{CZmS<_`Ov&{&rW5$)_CH)n{1^C>8lFT>d+0^18x zzx|9ll5Ge=7(AKkH9e{(A$K2xiomTsAfpy<#!hgZr*~Z|(t|r-=j>fo$6}{O#vOG_ zvxz#QAK7U~4JiYKccx(>R!*w`WY5XKtO^)Irii80Qx%0g;i3G7tq40oCVm5?Aez8`h##x1X-FFDeF<*X7y_LKuD9PB-Y$!dfdxVf==W4+Xs-CUjlpmaQg`R5=5 z3-Ze&_ti6HNOkL8iR@L?-+{iABV)f~Z(K{=6ge8@Qbg`o>F=D=BMg;faK`i3Q829) z`&Yh~Jk?(BGsamT6UJsP-Id zzm`zVqtEBgOfbkCQ&4Wn0ELTEd0~IU^wFm7M!r4#dMQ`BOY{s&`MxAU5E8JH8!YeioKMXR-h zcU?ubH5f*j!|dFcmzze&HF;$$xv>-n)r4&n3N3GqAXEdudc!6rPXU!Rz}*Sh7RXWM zU?l+zWIPBujaY2e3`?$Uf_G)W8aoOg-|rQy#9LRjK)Mm!Qc1#hGHv;&IyQzR)28BO zln=|>Q(^wjm$|NxQ)gt&1zszLB*9FMODbn3mm`ZqDMQ`{kQ~6CW_<PD?ihpRsw@ zIfrahFQ@5iwN;QI2?y+wk-BAREDiN#7zq9$4N4aJP36i(FL}egP`|;F(?g5(W2M-k zuRl&TN07tP>4I`mmfHLma`;nK%JF=o-2_$A;CH_fEr&`7x_$Yv<=m|GZ2w@FMf6iEQQ`khkS)~ep zs^srMM>++ky8AUg5KWnCW%zMsKiIL;aM-L+`Ba%HD^{R($?8D^Soqk;)a{vA>u#Twe%b)m0Bf2+#Z z1b$k)EeL&ABq;^pq#!Vhi6v`eYRJ*s-j05p-W@8q)KP@d(CyTXMi1JU&q(2%pd)Lu zIM%Lu1{JI2Ym0YkTJZm-F1PW@YnvZjx$tP_?Gm9`hM?nUzaZaY<4l>HTg|cf7Cw_} z7L!c(;&iwDe={Hdi^4K`cirhf1JZbSARvO~S0WPif6h}u+v zNARUsH-#?`^%YD0!Seg!7DEzVeKkVWh3oyrbs-}n|FV2ch9~$h`je74&CmZVE#zS* zBX@m#;%;aH#BuK$ZzGm;4-zU=A!#ybAumiXgie{p#Ov3tMB0YU8N zFH(Mq0Q!sM$0VuzYP%%@C+Mq3DTp}6U&hJ@asQ8Ov@}WOmp~U5aq5=^JY8IyFH#SK z(Edx{rk2p)i+jLF=m1Iezy2=511N?+191M&&=lu0L1X90VD-!K7lXOAA%m!cvAvVA zjiFnzZwnzRK>kFE5N5$%K1@qfQ?5Wr!8wA2lG1^^{!nC>{-Q;Mzi4|#b|l)#L_#tG zl~fj;C}b^_@7K}9xm~nw)GqnN4;?-M3c*ci@v=?BOzSJOfpv`#p#&IqWq42h51j2` z3hSKe&PSFw=+F8`RtG;17f-4mZgn}gO7=%(J&Xb{hCW3ir2#YuNo<0$j&(g&p9wy| zjQ=CqoQ%*494d;xIy+g41s6a0k&KWTcsQAwoUk6aIeCkmFa&r#*_48i6xRigrNM8V zDy%>({VMSM0_JT7A*!*aicx?6GapGo*a+Caq5t_F(d>$sm?}j+Ss^|(ynk~e^+ugv zj|fXl-m0~ zDoq#K$}aDSa}Uk#_>nOWA^KJmHuZT%7WLBKr^&s*sX!ObT&*|s+fFpq${Otgj zf-^DZNHYiBJtF3jbhzy6aE8_c1h@w#WF9_y5m;6fil|(LKp2sTGfrgD?qe?Is2<1r zk>S?nSYe?*0GR2*g;1v%_EPXD_kP_EVie;vij846QtknNO<#?qJ$*_d`2v~{!8B8| z?_9 QZz|;SS}OI@x=B<*=OTa(RG2s=zji_F4D0q)rZH^t~R2<{=}Px3lv3M;t=k zIT>xCn@+OZGBjOuiOt1D{{a831=j6ps&$}5c>0;OgH{Uu9baeW^wTad6df%ACasi{ zIt!#c0}F5bX7&-N(JG~+^htV=HxFEH*=&LPO;U$8t;UUsO1W_BB%F9m%t63zbWvIT zlG_C;M^uG-`Su^XKV|DSmCKDS92C`2Ct<0H63XXti%wfzWH&;K)S)cNb_4skZ@ zWjSFw#~cXO@vFH=2c^x@6&GHczY_kx|8UK~SU5pnzccU=LQL@g(m#zZXjl)Q|4K+` z$-qAmQIi>Kh{*wTy6o6ssZK~51s4cp@=^*9IK6#214$FK3^+RHOnz@Ep2Gb40NUa< ziO?kDh*cJg~D3Xmvk4qNmOT>Y+j@**z z4iZ0oCgT-89;&Hz0<5MaQ523Osg0<@#jvfl+?f3$NwSueGfdG;kQWOJIP;mS!vmG# z+%f_OS%TA&DEI~!L5VHi)0fddceGOK^x>{EQqhuC8pjSPlap#-J{jWe=DI`CfcG=Y z0!e060*M1K20crak`>h7QYUYwXMdWJAC9vZi9~J8w^hW*qLZjJ!I%;7AT>LO)Zqz; zqe@Z=gTz~v{^kmI?(^FgK^ZEgg|H02)vdkP{FlnaAGW)(pA!a z@M$f;kppUApXdH7K3P}Q_Fl+1Fqoga_FH;3&<}`%xlm_FAxp1plE136Hg*WWnUap@ zpH8H=bqRmgx>oxLqiC6&&w&kmbRBFmBm~|8jchoxBW-qkuvE~=R>7XTkW*N#TxgvA zp*#-N0V40`eb4qLy}pG-DgGms;j#H%q)wWyQ;a)!&9cHoVIg7^Pl~3Le|w)s1%r}Y zOhL%l);2<~UOD{9ZhG&U~09e~d zmM8R1fS8)nIvb`p0r2$njnF;m zynXM$dpt59-%G5Zi58NE$~2NTNB-7J*pjdIv;>cY3mM4ZUcM5R{Ly2a2{e4?ME$j^p%XPiQ26&rEBcP;KmIdc4LVeGgSI_Phhb*kHK?`hH+TPEGRK7Iy zGNsA4RiJrueXg(DW~B9U0eI(RdMeMJ<&I=au3-eHKRy=VGK7}@JeDhuFW5HsQ_8-( zAzDMLD!7`Wx`25OLmz{J!E7x2A&&q%JC6s?@kzpmA=j67TVFP+9PyV|Hl zM;K}T$EI7`+srZ@6rPeFE@gypxmu|zH}~s`R`b!F5I@dabnvS-31Eux`!bMc)=4vQ z2bZOleQtSGaR`d`I1+=ZC}74;Ut9IB&P-7Aud+Gu#}enL$2&dQ)Rb_n>qmQ|Cel`= zZxnR#c-zo+#(~ZHGF)WM6Wf=rF^loKKa9-6D=X{^FKp0Ot8y!BOZt{lfpDt?WCe;4 z*0K%*m-o>hmMJ7;uK?drkjwm3e|8WN%13^djW<;*+&h4M>a`mM&vgoJO-pDvU;e0DeJ*0=XL6kY#af^H~bk-SS4h0l(-Gc2dR!~O@YyTE5 z>}eKVvC%ZweY8e(d!Njlp=74hx$+B2O}Dy!QZ`TbZH3k|<>fyRX=L-k)4^d(5c&WY zbEds;_(6C@Gv*;amvAWZy^BH;)o+y&E=@Jk7RAIifVgXgUG5!|n0X2QeUp+y%93Mf z8&k7F&~__oix7a1sj&P2K-J>0bv4m;U8Z)aaLsU|G*KC50ttdr+gPR*WpK0hSL z>#%oiv1ul>4|Qf$R2PRkSj;(Jcaa)q^@@~z1l#}kO?D9GxtU3w&aXuJQi*XO|86p8 z0qoe(`OWh1V$uEVs6s1kfj)K_`@{YE|GEnRp#OQ`nHo&V-#AB7voDI`mDH6tB)b3?+;nVS8?R1FH;Vx(p(H*QRSN|YW;MET zC_C%7L_5`d|J28~{}WpF#SrSSuJ3Yr0qK$}nu$pX zP%v{EVZ3D$a+G^{6Jypm@-r3r*=gH=L~}fQPM&e`!17X*#u5UNI@!Z;Fs3rc&5;IL zN@^4f3qf;1r&WMbtsKqohLAGTptNNQzQS8ypR|vp$OB5Z)B;?ieJl!*#GK5MTP4ZZ znJQ|+c`(FV;<&INnN;6|h84dU5{cDPm7lFK9|v}?ckfUdGKWROXvrmfwico8Mqm|q z=nK3SXpinqwop1mMa~2(c?BuNHfc8G%ksA*Q z{K$z-%87I~v8G4qvMkxCtm<4MK>^YEVo9{d;?JxcQe zNYl~IxP63}tpC)N0q>_S`8fsFNur4ODfgm)RCFZxX)GZT1M7^$v#-qbQRSUEkY=k< zWL}qSg{AcF>yA?-BdjG6*f} zS7Ge0TI|u=NDIMfxDropwBq*B{*g{>{fL6kLQgc)Fo z_bX%pI6w71Z3zZ80c`y~oreyQ9nWSz{0DP`=?h#ms}3RbH8!26sf=c*eKqoZCKWQYo_nNiXe{Z zxfm#*#FOQDeo=Jb-w?U^$fJwOZ>ZB)Qb`*o4DR23(sW9^SuJiYv1D&WN6%(-2$zun zK-d(I&vN`ed(|CdJlIcjNpd}xeV2{wY2iI)Qdfy1XvZ?|MQzB`O&lRv)er+04U|5t zUlijfL~xnp?hhSitoTh3&_~3-fBucl|D5Ta7Y~8kL!On(O^OyCqN_e*6Bm;db^0@| zv(<`{JJR!^A`_Wdtw&*bWE#VnwP_FpAe0Y@i{R`$o0sJ^6hY8@EKnDh5cD+>l~8Pv6Xd4 zG`g>-xdV5ObhD~)g7old=l3S+f5HpTw9wKmtznFW#TGZCs>s9A>ZHAgn);CgFmrm` z1zB0(CiCVvRZ_<{ZbR7nyhtmk`JF+-TwP_{8B>vCqSt~rtE(U`_ZBm?_qDjDvxp!tC@IY%nZ%Om}W`z%0<8&A+0(@%STux6LYDqm&=oX*mfudpc8FG zyu&Qnvt+C|4Pl~wqPwcjQF!AA;5p!pVq7#W;LbU_xzcDmDs9U%PfHi8l%kvnZdd_} z$J06v7^vDPO?{GH@Y^#VR=QZOJ6&i*H>al6lFG;vyG+Dvy6n@g@d5#fQWf<&rftUR zqRMAVcC~$KQ>U8d#w=nh^X6P4yk){=$2qf67vZHB405w06WGF>n#3~%fJItv`BD}8 zH|TN~|Duff_B+#J(?`dlJAg5L48ID#FwL9!avN2CShj0 z!?IEPvib2yBhD~+R9}kYw=Ajd|Hsx_0L8Th>%zg^U1o51*FbQ$;O-VAXmBRDy9^cx z1h?RB2?P)BZowUb6aG0TbN>6@tye`+U2A&x?!ES|TD`vhRyQ^r@ag3g_4mi>PkV@J zCV@CZ$a!Flv03rJRL6j>J($M#1UF6mqn|#caxx@lHamjKuK5v<@=r|eIzrZ30P|&o z$<|R=Vjg;*dY1%Qylmg4ytX0kKN&71utTcz_e}Q;AMG0_<45%4Y@4!}*zbMxdb@F@QlPV`pO~*06S&vZLNA zTS*M~Yt2`XWDrR1OZ=yKGtT#bgx6WmoF}zUZ0PnQ#$HI>!NJ)RH#=t``!^5c1-A{o z-43rV?&Xh=X0Hd%Q=Qwked>NcADnJIS;qxba}11(+}sMOOhxqS&QxJUel0W3V<Kal|=|aVGQlJwQ``e@?g|K}7^$h15X*6^cCYGcE3FV(r92qdz6jZ!oOUZtQ;7v zbO;)||4->hJaBgmF%np~0CJNvd6Lh6`7AxRt-nGbDl}N&BvyDraJLgKVzVO)Su)g^ zYAs1UR7CC~L5GUYOXPJ(EdRKl04p<~3%Q;U>(wg=aqIsA9wjW?-#dDGSnJw5gE!t# z5`gxV@(cz(P2oG{(2HvYCs3oXm$d1%S&+LIJ8bYPtBr+({UCIZ4RPU3?OgrKY{%j%(n$3IBuqVgK z`DFchlU7SI`p|@SSqsedL`4WnV4bEe2S&YPSMipg1yDLXn9fD3UvewxX2fwSM>4~Z zY5XdCOC6-5y;g!ER@yFaPo`rXUR?Nt6oV-_l~AFRk?4>i_)E9Ic&P%TE}*1E`oxEg z;7|j{jZUj!x69Tw0!}^EE|ilCc_fjFmg+YT(GZV8#^0ExF%Pqt{^WjYQle2I4*x|! zc4BZfh|bzblR?H9CZUF(E?g^7PEpG~b;uaZ9Y#rmMiXX1dR><+zm1a)HVdO90kP!l zf3yE$)%q4|hTdsAXeBaZ2@_m0lR&^{G}(}w`icD^3=jBb!#G@^Y5Y~*UYFO;0Y`MA zX2GGJi`{0i?kq@8-(t&MB(ru)a!;u|Q&veVB+TPiy16z2ktz# zzFzpQlkl7*-D)1=*j7JlSc{KGVIa<5JU|P*{Y>Ha?Xj=CSiZG~l3aa4=~^Q4AMQ0& z*-MUKFKX}e=O1+v-x;%b_sD5_=gwjFaSPdg6wdbD6$zQ)Aj}nPyNxsQx4v9e^LM7+ zU2(}RNS25&Sd#owPUw=mEo(FFTm0}bXpgJk`{A3!eh_mva}-w&#Z3*Y*s6l$NxjrC zg`;Cj=;7UWU3|^XNSGU*4e?Z_Jqg|5U`UNV#y9uG?{gg+@3ONo= zjEG4*I5hED(<7oX`@`p@=YpuoF~QFcYh#f4oIbb~D9$)Y=JUDSe ziXbi9Oc4sF%>8i&lVb>IJlQt%pOjWAGus#W`16xP&deND#NLRFhNgn>EjX+*XInhq zzZI>FrBG9qeGi_U92a(>r`Ff~`5Z3S3m3Lw^TVMeMu-$s;5T<~XUsrWs-a*Uz1SAN zD($bMspr?^m`e!Bs%^wN-ZwVh#LOGp>mi8-1Yg#oU6v3^_Wpu)=nZd*nLF&{#~;|JxFrA zmpM9Yvg#f+ulCL2Lvl}w8{K2h{%UBzcZ2EN1#(^3Go)U_KU5ah`h+WT`fLUh3`s)5 zhLI7rfw;yGzFeiqOyT5to88T9v1w5jRi|q?8ylNKIq~uy&Ij&P zYR0+#!BFSx^PQ0Xfyd5j)WL2k6&=DYnV&Pp+G6qxi)wM#om*1`>TH|jaEGkZsJ@{t zxy4mhhWIF7$EeP*Vm+$(ka6mGN7BtxtUjg^G5@UeO)(Q{6GG?DlkjAt<9>MK(4y~< zZ*zo?(k(ph#gSD$2dXY|`bCEHp>fU>&BbMby%{{BxI*@&7w$n>1rkOG*qw1Zup2xv zIz06uJfGv7)CU2xB9YIWEUg;T)@M+~g+zSEZ5m^r(DFMEICP&Cf^_twOj8sL%+C%J z#%$i?aj&8UvpP8T>K(6lEF^4W_APw()P(s)LfSxv+Wc7-3)F3`$nfimf5qJKbS4=Me!4~-^vFrCltSW?3f5!JPOG@v3+d&L$96P#&nOi zsv?Q^0RX9L?m*+>^%lz)*Eu;O%-c5Dzc+G!ne)Px=Sx ze}V3ASV)`E{zcjuc_+)NAPWl#78vFLQeK!?fD{vS;=J92`|KqCgZB-Lk8XuOK4Ww- z6SI=?==XFZ1yxcbe8>@=c;DZfEN>M;EGUY{C*<~HJj0V6tGwb)^2mB3`$%##-E9PC z?z6c%g31Ofhz4m(8DJC|{i^CuQi8n=(KI68ek(2y;>e-c-diZZxOTq@l;sYph#86T z(k0SGC88hQ_S7CYJnIJ6*pU*6y*T{&qiL<6?D8QuBs@hOjp@)f=~N1VS|(Q5P=L8Y zF>(Z-l!=l>LPzBja%bJxa7$p37MlHcrQ+OI^~En>BW!YFMECTq5Z`F9Ya$sQsEbbU z!Otr-EA-v;UaHn$r(L0>7<0c73PF(%P=00mRVo20m9oco?j2+W`QAZm-&DeWl}kYu zX{S%BNWGXI2h$Qw_90Av*13bzPhnWAlEa0WPSL#M8_On&!l`u%#$<}Hj zV%QJ<=8D_Q969h~8|xnV1?L+xKOEb_w7pSX_S;kCH|Xb2$h-dEXgp&4H3v?ba5l^t z?wV`Nf_Qp${f75MeP<3AK4-iqC*zLa1wNIre`~^0(6O}tiHYW((}e}7oXv-mb9@*9RwBM!H19*kmQwA zBs%c564g@bvC*9R;l&ADQKsHSyZz37lO)KuYx`9n`v;%mtcK3%obqa! zH4GJUX4gNs-NQiV;bR2MT1~UP?Tc#tJ$aatx>N%Uw(vUugF3T9xk;IL|F*^+tGzr! zjl?K94b#TyS99qSbmxz$?P7N~iT&_6vNVeudOSCOQjRY6pBZwHT+v!zw|W*H>T<{J zyS4pj0}=12gx}uv`ic6$hCJs+ewveOctc~pS;(ecTBBAVtQtCbCX^Jzl32k`uX+ z=W>-%s^RbJQ(U6;wVv5fdBSx3!`x%pqu+VQL?9(?sx{kRa~T;EU%NV=WVW{jGf`=JMpO)?Dudmx3_fyXB*L!INrhe~b zCTEpo6bv(D7Mw87*vI34iIER`jHLO&mH+jidqc1zFP0;UHooS4yu#t`QWM}3hEFDh z6_5MkZ4}$h3dx5Fg>pNQc<(G0gvXkS2xX>N6yx^5(d*~C|ABu0MSh!uyvTndrfkSw5Z|G{%$fK@W>4Qqn*r> zkU}jBPEo)^b?t?zy`bXOYtkQ31>jH0Y^ccW46yy{g`&llkQc;@?_gInN<8qJc69i( z&j5sGMo~aCRN0&s$cgyxvn%cqSwunh;Ud(pUJ-$V=CBCC=k+x3&8@IxDX9NGR5FR~ zgDu3IJvgbGk`T;U3LyuHE$fW|Psc8wLc(cvERVe4Ju> zGY!BLAN2_jfbU+gp~6Pcx0*Goq#<{XG5y1GByt27__X=@F=+MD$lp@`$03bvlwjx3 zu}h`Ce_{?%N9Cf4{H{3r3y;`9UTV;Tm(MRT5G}>xxcKvc8tCP|BoEYPesm`@*z)HH zWKFL(te>IH$FUXdN_bI--zsRug_aGzGyQ4$Qe980;}#=oTV?cv_G^pi)peFukLE<; zqLQXi#{D`=J^d6Tp9Z-+pV$Gd7-&djQiZ+S(mr*Et7QC2^C+FYp=x+ zXfbMpy22s1E(L#&HB9`_(x~}I4UrJOq7Lx$n_*r}S#1Zc^9Kq=)#t0*CSACPLbXye`~xS9rugCtjx-_WvbWsR_oRpjF?4Qnp>+B6tBd(UMt z7sjHk5sEaZ+4-5{uU)GU)Nz_~+Zl&wCT7O8B@(n;^qaK2(@kXi=AHTds}UcSO9eKc zE%+^582(e(?$FKon-mAMa@@ybDI5puIJ|+ah z>os)RPoIpYZkP=hiuS)EMt*+>UF+oaAjyM$@;X)ezDNA<{W%x2>{RoS_1>`QQg1&Z=@!}NN^gfv zVEOmWnrY4X!H0{ZX;@snhA$aNxg5^(YjjS755rg;)`gdXPmQ6t2nq87tScZNCDZ54 z=UoX*qHka_#=;MF%g&N#^9&msLWXQWqT9qxtn`B5Ljy5{wJ*a6_?X^AvVqt5K29fV z@0%-{a3wkJjyXEdiJI2Jow&rp)-Vcj*|Z)M5r?sXz3a_t`RnP$-BBHs-b*rnK3vt# z`Ynh_1tB=LzPi#jyk1txb|?kaIi1U(RBYKf?1sM<_dfUg9Np%`iKb0T#hYV2Gi=XT zh=xF6e{W587I*?Fzp=KPvJ|E&;6_p^M~$W525hULnHKBdmHAA9rP~lvAD`% zcfIzP7e4NhiCN;~&Mq1h7GU);Ip$oiJ?be{Bl zQR3^XFjo0tqj4RD8F=o+x?GPX#SFF*`yS%uJM~1SsM>moNuMa2uFC=Pc~QNBL2Mt3 zq)QGNnOu%4SyiKuB;GUw*|C@RA|ihKU}tm@pwkp07;E*Y=u^5ZSMkhi;Mf1-{9$Q{Qipo5V5#4`JaN@=enM4E+IHDwz~#`q}!+{Y>GXZ>mRJ=F~C z%g)z7BC#`O=UBg6yfo9wWCQj;9l-}WwfMVhW)^6cjnH(jpjEJ-f~ZAnAzk$9DI79{ zssb79-gSxcsg>&>Zv!*4WVzWZQWAeVA!;)oEoRG|7Fday4w_rW(d^}9$s+exaatq~(ahva=>8CjI=*Y&zoE5jze!tQSz6R7 zv6DqdfZeXwuO*OCQ0izV9K`N$v?LrZ8!jm1=0`EbrPZ+I@^Q?Wh$I9t(~zo5QY!6z z!yrL+lFOwu+y$fO@U}qvaHJGMc1+(lJV3Uh=o>F=Zl(0eXps6usZdblUd>L)2tlp8 z1(k(Lo+jr4*b#>ASFB%$fV5%=A~iKNm+sSMS|58kowDE%=@Eg}X=6KsCX^NG9H z`Q4zCo}<2F4+fPWhU};DN10&A2K`{mnkT((%q^s)Wgj`}c^yzQBow+m z9ZiB+IRM#7ktW*oWaS0)J6iiD(Yx1!F+}VYmLKW}Dp2Gar)87b6tpMakYuwVgHeQp zFz}<1OgHyZOVUk>E!{(kw>KO}y}$*63U<<>o$6XP*dP%RnuY$KT=LcxaoT{ZxjOGt zon_w*UmP%#ke5SFermLmVW}ggipENF`vHC%`eG{*I$tMPG*ZdUaUUn-fGq(}c;kd5 zgbSYjG4}Ft__IC}jtYW%b%0TJV))&)B+T$cKN^cclcH>g<<1p<5E3B zmvQVcMYX+1`0z|$@s98cfnzQc-ODrhqOtWZa&l~oAr0BEYT(oJgjikcvW|%@ap(PD zfA3EiBcVHq_eCU2g|v)#tE!;UjNyY*%cKJPH$Ymu`k&&2N@E2(Zd#w5D++NUnyBkW z)_58bCaJtlSe7(ulRQR!i_Wvq5bc)QK(C|=wPO;nG3Qq&FVwCBGY-GTT_qC%8FXA(J;bgzJAn2jIe&kb396s1uF^S zeg-kUTPV|>%rn586lr+PN8_>#%wMKsU(wo8m9JZG7ei|=&5%^g##;J5bP;snm*Mjg% zngk|=JJpYayYv(>EPOYS_wb_(DC4CzUo=Wt0PDC(9TIWsu%y=b9}~O96x*f8Gq=Bg zF1C1Jv0MsCw9Z);*$Cx@$4na>7hUb@0tlvMqC`oyD~B_S*7Sc6jv$@Wh;F0zqVxs9 z&kn(9<6wD{Dj^W0HjiK6D8X<|oJp$3#KU~2F~L~tbwdn3DRg$Ev;K~ee7bF?f?0Il zkxlnq_H-MbJ|Q45^R?Zq5X)8gSV4f!qHY0wPO8VOq~;sV`2t81*A9QlMB!~jNI6TW zLG@jK(Fl7#G4C*If~)@J3YBP2!$l;>U@s@WBnjqMiOM8%)9!(jA6H!{0-_ILrE7m| z8?*VsM3T{u;!=rsw@>nDuRca+G;k4nYkwkOm%D=W#Yw{E7OIT3Wt|9;&a_d8(NAZy z#8%;`+vE>p;o%EM;f1`?GZdZ4x2q)d^)@?uGHla##5qxPcQ1MaM<_zgQdJ*7W~xm9 z1oSWaTRH85MV5#O53-W&Q<{vNL-kT+>;lV6H^jU^YoTTbI49(co7Owo2*v0ghg{|q z(SVKGwoDmzKMxn#U9a|@GoIq6>OxB%+#pI_7*al(8cias6I3>Snn_b8WXBkJ>G6Af zL;l9(U#VlAVmCB2tcS@qIRaELk#W^O6eC4*Zec*oYJ}i(kDx@)1c`} zav<@Jz2%%$5=(cr{iyux#=!0N>~3A$Z`wyx?o&EorSer;fkISS51+<#&ESD!Ozql3 z5K-ee>&o2-t^CHX&*&j3RvTGry)UCcQ1T>i;m}fYYkRnyFia{17;@)Q-ihzeU}b)k zt~o=GK*OM1xX46bub{UH3a3=XB$?yt$a7JDFQtf-$rL@##L+D>=0(4WMz? zETd88PO_|$ffoAn+Ybck#zN154FxKYNaR}t^_(SNGS_hQoUQVy)8lE9%%1SxJcssZ zG|b-$7@df|CY%XMXK4&^Kji9zS`Xp6_L8S#>QJH#TZ}E{?#i7UKtC;Anqq-6nUhkd z_@6}L8iaVa(ET=A<%g80UUO#?fJHw?QaLNSUAVy{w!c-cP4kTn@821mrr#^0ODA(J zZYexjxqc=A^hV63KZfo4g$2SGaBk9>9*_j~<(CmiI@hjiY95C5%u26`8EB?H#aLOTpvPZ1FBB*YB9AHV>qN>k+D3_G% zS0pST!qnEn^@3^HGmBQL%JCi}$Np}M=sUNKXR5i3j?QW`<#9whVisB4Ui-7D~P5&3SGx@uavOUs77o10BBY9)?*k_t1T3Tf@U^FtIe)$VBGXNi-9)tr?r;N|9ccbn?RLr_8EEWyd;HA@eiME8u53>ag8XSu|QT zsB3QH%hnfYLmFoNEJkf+YDEdT(1p$HGcpWVbP@I1owfchEKotSR~h%V!=r_l3-;nU zNbuL(&ku3j9~1~K%E9=h`Bvyzd%}*TKO>g|(}z2T7S`DxF;0=hmTwz4bz%)vi*k0{sNG{z8SpuE+_-FAVGh z48pd!`ZM5h=cM*ah#1wUd&$3<#zj)mWl^h*O!~z3vu6P@+>2&;6>h}2KsHN&$wbOz zK0ToVq&%4E>t2+Q;V^ zkc>$B-r>{zEhDMR4D0e4XIMua8=NO*)J}ohMb3&i2nN!YF}A(CoHzh zV`XPV)d`{X$|EAx%DfLMo=@>@Je%RuXJ;CHAYM{~P$#>i$g)jMBk8YRis>}~$`GFo z3*cy$h`;2UFR=&9YZ*XF%LmNeq(!3>RaS@0<*pN+Et^}(4tM1)`+WC$>fWN14F4|+ zj&B}pI^&%`Yee8Lx<7rWgLfmf#;zHC2AFd;AgRGwaW)5Devwk&@%0fg{-mV&?dXjP z0*L%x znic9rY^WH+=Yz+0Qf|hVEKb*xgu?)~4y`O(<%W$;-`ML&W;fcY9NedGxjcoKm;Vw( zRlUee-zhClqNi#sQi;3O?YD9a0K0rd9{^3PqUl^>gY_?o=RJs>`Fl$EPXcC_1@8^$ z_!ZE%f5^DuBa!5lh8)32_Rf~ofJ6#xU2;CrfBTio3^2taX5J}i>%vzes0vr114@4b z$ch1aL-@7GD|2QI=XM5Po5@pGu=TjjwdlVWJ+#JaA?@V zU61h^5BE%8u`#3ZIv{Qee&cJ)kOQ#8wi2a_aNZVW*1->s$3aFhWD3gL491(Hv<8xmhi#foG9_Z>h_3O%~QzK zTTrBmdx`h~>Q?S8*=H!*qltk^@bAsW9jz6YAs*iThb@vf`@vHlK>hQJCD(!)ibf{s zg+gAv>;O5a!dE=tYpBA)78x0Iw9EYy?2%vvH zicn@@2dFGBL`Q`OW2h=aV1K# zDJ(j`$H2%mS=sn#3>J6Fa#EzcA7nWGhrgT5Xj*rb41+$s>M69R<>@)T7(o^A`ZG&r znp)~yA&~aRubWmy0j%f(6*_BnG?}A1YOmcVHs4s*4;vJ=?``{N9{m3tJY8Si@42TG zPnK6w|6T?Ii6{s`HU!W0_b2PjaWt5=wj>8GeA;#CvtN{N%KS4aWz(uj)6x-SWF%GC znAl3$vzgOz`XOwX_e)lW;c zEo1V6f>7+KP@G{1w?*#ImOYv1FJBj&_FIg+@Z_K_1g=Q|F7ib{dS>c1ywY&XrfT#D z1W_p`#SE=fIYk}&)Y%B?{VmsHu}t7dt8ybtHogXXTl&cgb>26RZWU zlZ{+Aah(+xnPp$k&g~!Kn|)BiE>Y-N*x72EC0B8UpChVU$B)jlHD$>x@9ElexVk;d z$}y?+PJ?hDq3ZFgT!xN(tl6jBJ~cE`5Il^Jn1{Zyai0|IdTvCuS=H{ChtP*T0eULL zpPh-tr=u9=gucaN%dM_GAq+nAym(za-|}wKL_B-_F!q)(_Hs^1?;Q;m0{4YS%1)*& z4mdjAU=O+$){+ToE`N%uML-`^+R_=7LZ!d)P}KZ~uB-0$niLIng%Y2~1rHw;WP7U8 zNj6_>=41WR(vZ|Mr>Xo8U6;VgS)HQ2%SCe6`_An%Bet3fD&cq6d#NYdo{5_?l}N|| zN&&3C1f>P@yno0rFy`A{g_5l~MI1Jxuv@Q;vD-Ge@!Q%2as}pOkV8R7!qhFF%ZThq zz(JfzbPYn{5kcV#{kOB+E{&k9Q&Ie`Zllm@0g3}}yfe(;`<(?B3WtNvR-3qFpFgjW zY=j_Wn6_->%172lXX5Nx;kYEZRzG5_ z@c;f4*D=CRed&Jn%J^~7!C7&Egb-UN>D-pxg%fPc8UnUxOwFlKf4yo7p`+v9nEI3LWlKRwHk2@5_GkBHLv@P9}_ zX`cC79&OPmvW^ozL9eYL`|W_@MfyTYi|GiPZbynjj=28PZ+Q6T!({WT@wSZNS#jEN zbj#V)@fNTS_xFWwpa`vtK~e8>UX`76jw;XFZ`&xk3QoYfPA4G2_$uq_*#MhR;y!yW zxaBKX40CJx1R{|Ho2!aIhC+gUT&>p!%`^9t-Y#^^|<>#qAn z<3~T+PvNv*U(J2w=yaG_FmqVDi>5#(7Eh!KjHBXEVp@I!XKx-%#H_yGjSZlV`!xR2 z!;}8GibFZo!T6TzVx7KIt`hG=ezzsLg#|;cIn`SKn%Fw-I2fqEtKO8T#&K=c@|4We zg3P2m#&LcW0b-9$8?yKUR24VB*rp2raviLc7q$Hg_|o{`_fTIn{OZ=GmTRJ?eKsL4 zaPHz_&b~bO^1WF~TA05!&u{fKHM_5!Pb>24itNUC^U3Vy6IPiv6L6scYfZ@k8t)!X zlP~{#m!CI4GJlgUyGZ4jg8s^ZJ zI`B?PYIeo&oybFfl(EzGNR+DBhtr#P+Cy@d*B7CA$M!hjd&0}=x|_)$q<0kzMdFOK%t5Yuj;8`iv1ikN<$@rG$du3tXUWYEzh?oDP zQsKWr4{;yKe~eV!7K-e@iLIK4iV9u$SFe1)>T(eNY4i{zA-5$7Fo*w}N-Q)1jQ?MqMRHc6Dmfj1CpVl5*9hp z-`lq}g(v=mEV}D|(~JMoQ{T+cpn;oO$uXNR`GG@!7j)b--dH(Efxi)QusP%eJDB1p z4Q}&w6hH&z-?Sp(H}3e~5HpY9H!E=XU=eCG)Ml1xVmRm`?=1`5g@!}w7-YrJ5ae?T zuooJ8UnSnR0BkYUVdv$LIQOl))@!~4QN;cNXMXl zlhjfE7lbioP)b8D^Hl!-9jHkm`H$V)GD21ZwJ=jb@n5xqbOWkq=xFXRu>~}I`pib@ z3-!zolS&+_V46nuU-TDqMrs9B*bt&z`uo}@%*c#(AlcJZaE}uu0T^qC8mpP|hV&BZ ztlLMXRM>+8Hq_J@{2VSv*|V$rxH)s zRC!xqEt17rgNUxQI;*`0VWhBAbW=?Dkw(#i3R?;fP1G~K=0$sZnrhTAhsw+Rb7p%m zi}VE<2pflW{my+n-kE;g?l2gVCVT>{tlm#k`y3*$weKBp(SFypY1#S5FwpzQMIH;|4 zk@cUwElTanrYwzC@zk%@JE|9yvg9ssCl?|VC8+G!qIs*CaVFaaDYlR)${#-`bF*H- z7xXQn23u*2f+7@s7zt*vj^jb`A3mq0a)>CKW1iX@>uhKu^bDI&{ghJM8pF~^mqO0} zj%+W#k^K5MjqM~RYad1mrK(JRCkB$aUz>+Z4}Uq##Y=c3X`7*~25`0{N?*C=%d*aJ0~xC&VA*UAroP zk7Y1Gu4b7SR%Z$75UJWYG44VH)MRKaLHbKy)ET7)k!ddG!)QiC8Poa;s=Zp z5QvQCQcd(fbllB%H;G>6D81--seIqdJX+DSbXWc&;+SP6ST8c))^>BSlo_isPqPZN zoV_u20P)@eSji88s=&+e4y_wNW}Z#;fzM9Mgf)Nd1{RFb>J3{;V_n>kzvH4V^Eaf$ zcr`qSclVrE0PTLKgxcN{1vhs4cWwQAU57Ld7WZDbV@1D~$xm@FJhBd|-;-QLolZHP zj**YkCR(alj_}a8@$n6ia#FHq3KXBDcvY#y7n_UV z?F~;2WhY$c?Fz&0*TrPMsZOA`!6Ta)NOvF=b6*MM{wI#py0j@azd*W5K?!g3E0LsK zTq0lQ0cG`KKJw0$JP;tW_!UaF#kM-AW+L>#2#+^EwZ0!dHW3=rqyNUUN;bmT>7FGB z%1w1W&15dP6CSV?n804X6V38V*P5;inD*S`S$8|mzxFy=k>muU0|o}(`VOR5CUFmR zS`M&AjK(T9&(qHtryCH)j=l3{B<}^E`W8o`Z9W4{>wZ>5d0H=p54B_ZwKa;mM_L&G z$@EnA4FRruadLfoTQF_AmS0=6Gac$c>!B=o?h8dAO(( zsC9VuaBR_$c6^`fxFF~z27dQ@JIax-Hv(4XjmHcPzsc1$3ER4kp@i?d8O@_6MXLdy zF#*%87v+AeYx_dl^{uM^E8pKiMT)EQPUa{k?Wz%eC` zSkN}e_)M>=klQ(G;%T~*K<9+_ZGPjcdMvmvvj{C?MuFPr+RQw!xzR4=bMl(8`jRQ} z@Td|4x?+mFVX8_ZTu-j9YXNBX2s!HD#;o$RG z=)SEVMU>Uh66?FWTgealBL3m^pOf|k?j~#HB9u=3)ciC=iDo-a*t0S%es%t^+1K=E zzCXh70PUD^EHK?hNKd{`owNPb(+DP%qB1nHK|#&^)=z)jf7lExKT?P3IdKYf7*NE8 zO06}WBUknOuA%b0<31GzF$OoJ`3XE+WrzqkvgnChVk9~dI8s;4K)QAfYhDFX2?niG zN~e@OOUk!5hb1nzPu`+V!k-Zxu}JbJX&=r`2_Tz0A|a|_q8GAmq1H>|V%(P3G0k+g zIWpg?*z*&DQ0?=y$fQNQ?u$$erI}xM+pd2$Ai5|$a+iC0f9&p}x4i2bGL}U2l|Mdh zAybr-miH`>EGpX_&mtIk*xaud=AlSLMfJm@T=X2DKw|&R?^ut{;d8mq{{k*XFOn$eDCZ6_>t9UE&VH197!m+%|8r;> zT*Zt{_Ln@R>*V%D9`~8;6ZHUy&~tj>3s!_?TurWiA{Kyr^)hZ2(=M<+iddjPxR=Y=^cE&A%xt=p*71#X-J%Y* zv*H*}u5JyxVvS9|`1fV?FL2jfz~@vu*b)!}g_>ASZcc8gSwuwvdc``3B?Z<3Gmx4& zHw;z~UUWF7VS$$F?l<$3*YhK&f)Td25LlPyTn~w@xti#b*W8jEXvaL!^_8;i%?A<^v5fxI`jGc-={qkwgpm=oz`OZ3cTP=hSe8ekCVCK3P*s#Hx& zH^CJ1$33o7w|7*^EG*2Jaqoz!`u%HPo5zKl2r{KI&dmZE z6_&jzKZq7I^=_m5wp73X3sf;k55$Olo4Nev#S!eVYWeY~bp7t|)a#ht?SG!d~luKZOyNXXY|tztk%=FW8tQ zop^H&<&jn`7|V~_h-QX7EN_~7wCSAvVqt-*!G172yCj-VWqF281gzG=L^>PTD+pT$ zob#PM+=NZ1-~2a!8t1_ze~||j{~~L0{+Ur`jv0w|94!QMr@7knZEoCHO-?Z#jUI0O z5{_TW86DO}u=>QrK=>}k{kbG8{#9F!1v=0CxYL{&jpy`b1`hT>@9-NLE=xlM&=`6Q z;W3X?cw4iU2CdMN(SWTu+XU7Lq(j6rE((ij66%OGt0+GWAtR>E9+D2I205ehwCE_S z4q5D~nlFLk+a5W$B@<(Y-n)hdC0Is;xIHva4`EeY z-pL)<68%j1*e~hbQsnAh2$;7}OQ`Nf)+6AGpTOOVoC^~KCU}8tP z;3Z0!stg_hL5ST)9CqlkHT~amsNW)_-^Wm>Q}i(gU`3; z1?kECwg^lbwxc$&y@TEzXcuC~G%hfE(<`^)pFo$1y{U}X(MH`q<^9ZauU~;mK|ysd zn^`(>()DszADfWy+%`(}D4fB;5jK3zWWL;wC{Th~b80o5D@y9rs^0P?et%I~J*##@DeH|BOJ4d)O3A3p^ zBg9&@XjW;XQ~k{Bzd|&0PS8L0RJr0cQdD=AE-)Zg2-ktmBZPM)ph~}uJv<#n2v1+ITBSfUQfl2OG zZv5K^s(Aet3du(v`4?e%9D|uh#0z!S?{7D|OzC`0{X}MeWtXxem7PNVA|_0V+Kx+4 z^E6j!W}lliJALqGvn9&0LbNEtAwT&}YXo?!{)QU$#V}(Wd#9k-()7rWV9m(0x=U{_!$?9KVzOZ+dL}~a(cqYCVf~d5UVx(5;KwRaN zV1<{A`VY(HXER?7kT17(IqTcLRxNu-4X#d3)B%7t&i7np)DI_bsED09E8q2a7q(iN zP*o;dC7J1RhrMFqAX5-_s7ZXqv9F*+emzRU(t`~m9>*MorX*g_HGy>pO11T$Z==5Tv!$Qrvz87wsRhIM_Dp9uD}44Ne_NL5{mfsgsxAz5g-i<9Miduw2Cte<-F6I zaSA4r)cw?!h71z!lF%~|U-$<}HlMpnJl-l_TTs=^YG>J2f%8|s*(HuP%uq{SG-pYh z5_duJYJn?s_6hEz2NbP)1ORoJP%3*e2s0u?$AmCDr<%=+zD9(2p^G8*%OvrL`-p3p z6M02MRM@+V?I>UP6z910vZ8HcP@SU)XW&8$kX8a! z2FS@@UCFQoa{*~cyv%m|1zy!B|8;g`kDwT7K5Yn$uni57sA)a!)uz}OKcp^~`iJ&@ zc?6!G(iJTk1|j07(J5vO9W%8a>@v1MA$Tu7yU*Uw^QX zG{yMyRNpZp>7Bt7zV-#|qA&0ONNz}N!&k;to$g72E1qyrRI?QO`@W@=cHjB#ib6wq zn%A?=FgxHIxdPix@3a=TRv?I1@R^A=UTo`Vc`h<@$YOS-Q>1@)SyPzAwWn2oWEW&` zA*u9C^Zda>I;ah@THc6*t1u`7^9g$|mm6OB(4ECiF2nsvOC*fp zHl=C4QtsY!BxAyV*lI&7tx_V{ZX6=cbXuIxMtuJS=;+iWko`k2xppxRS=O+ws?zfY zoa(jOGJK+?X)DSrO}a`qOc}+=)X#u^9xH?~!#vL8y@4MejMMHxVUmI}g8 z;#kiSPiehBt-d9mQEfqAo)P9~ooJ5@b(b$;pqUUJLH4*jnSuhmYDiA)oI?1kNF6Yf)AJCC@t z+kJI{<6oY9X6EP$X6nZp58>Lc&VxPf{~+D(#Ur%Ov#?4#lH0NO3kmB zbl_(7H=ydmkhG@jcr_C+?@{6tWmgW@DUZF{mfP|)TiW<_?`ORl=83EF^4hKFVP3@l zW@VsPD!x~NVEmLo@J1&wKFIxlie>2;J8uu-1U9K^95K8Lrx_QNNbEbJ#Ftq{r=9#; zY|}1@EmQvw<5TTC$}VTC#K#p%zgjK6MSQyQflDcLWcv2U3DEHg* z-gVLSa(KBh)grOpn13JzADLyw5`qK~jIM4yd#osMMf01h*krr)bYKP+W z(aX3CD76JvXEaN>#n@`(M7(iDXBW0{V44YwC-#|uPcn1il~?@HR^+8G=JJ!)khK2X>>w#Ji@O_TX&&HEJXpb$J2E1!w~|n zk*EH@bsq17t-%B~K=_Ib{u)YVU!feRLZ_$AJDa&AQ2H3f z=#XY>;?RbcPM54%=@D2pu$a008tCwQ*wju4i`Rz7<|pt z#mvtfCn+F18I(|j`3#Qxo;H?3 zJt>O1Q~1FI+Bnq6n~;f5TWlutDe0Ke&SxbBC8z`MHzCA+faT_07;Fa{Rym7l)RRy! z4L&Iw&+3Lo^O;hycn>x@5(>iLO;Ae|?Y7b83$lK)Hef;dX*o3wQ<|XG+1_g&HQv%I z-(X?t9(tS6Dk4;&KX836I%9iYyt1bg-1wV${8J<=W~ez=Ke>p-I{Ox|XxFCNuxHXH zap2eS`-*277yd&WZ<`DFn)Nnh!1tUybF z-JQ^7(<@Q=3p-CSnJmG#vm3C%l_treu&_5%#MJz7`Dr3Vj2Q=`y`8K@&H9DokEMzk zp&kJDPz&#fSY6QfQF?JOqH{!9s`J!0y`UYKdPOs-2frwhQo6fhlZ){+ck`2}Dn0^` zmoPiMFRvQO3v5Fdw049YE(TAwJ0SHi|DYO}o}CxL8ZJ2pjUq}XYU(qYP>w}7W1;rM zsdfFWF-pYtVa>GG=VK-OK!B>O7B9zDLoxtu^TxPtO@qbJ`ELKsd>UIdinR z)5sCOEH4zV^+=S5hsx+Mn6160VXIjBwvg6wG2!e~8Y*(v&q~spdz_Wa#p5eC(dYsa z^4D>Zo*B|nB5^MZtoZ!UWuRZb!mUTTP^WhWgp z@Ei)vO#WCL+ca_-vPucu)C5vnE@Oa_>4*$c{Cwy3=kE4lb>&_8vKcBYewi%FIBFne zvREW54HjbL@L)}&&G;6OqeXPZu9B^Ec#Jbq-t7oZHyL0jqt{4p6y)>(UG!4lM;BE; zu^d08a_*US(yD?>*1TRnrK|~AVsyUsROR%fUzC^~`(BKAXeRCRnwh1_@Rt|{_ zVIM9NAr8O5K3hvwy*!_=_I55#sg!cO$|nG3MPege82m~`S+&B~4+m46J9(k}lE;6{Lt8D$M&Uod zzB)!5`wUmMo%)0nQKARu8ybhsyCY=UJ-u;R$R>8uZG?VzHUwaEqsPy~5Zp25lWmh} z@xC;YRhDxF);V=`;AE{Ke8tJrZQutc2roPCO@+=z&t(e!c?~8r4(0;5tEiE{Fqm(l z8aFOKpEW&^SWDEp_-vgMrG&*;6>-B-_XgDRQ=8Jm8u6msg`xdG{&vJ2Y?M^F(a&;x z|1-(B&@PaAWl$+z?8j-gm!FA5hQfr>ptCoNiT~XOU;z@~R7trwW=b1%+g^Bf$DsuC zb?wYL8@eS0;;Eu@U?vB^MorkGff$$llHMubocUSRyPv+4&=7JAQ;xqIHU_#r)BcGq z!f)D;_mxmMVZb;E8vA(Hw$vy|jimrbTRP!8uZB$FZM&XmcumKk@`uBziJQTEwm&d1 z5QW==Kk|xkWisWY<8B=j*pY@~Z{b)?2G_-Hp9!suDH;mmmTRK{dHI}4vq?TyviXhP zSR80)c^6VykAfx)*P43oU$jsMtES=4D*J{&lY|0+4W>TVp||=hA4`RTK=_` z|C;HIU$o!W5U0tYer;XNlWY}m<>f6}_ar)wyacTrGQssKa9I`jzr!#shkWZi&@im2 zWt3$8eH9<`8Q1+iIH5T}{2%n-BMVW+zpMC;l2bbrpddc*A9-|Bbs(|uziaOwh)E@E zKv9daPeA`J611jl4wC8t`R;>&=@1t6v#2@X22x|R&LY2pyK zEXvz%3AEr%9j=U-bQU_)!S_{=F2KVOHoWmjW1J3lt7OyKvAs7iG?8C- z@of^7NZ6wjQGwsEBaC3bTYy7a!V2dnsLbI%R*ivo=nVyCNUhX=&Tjk!oW{SHXX@^I zOA|+2&pwlfk^YTRj&0zeR&g^(BTN-wFJ)9Ou#X9vrWZ}aB-M81V< z_}%=aj$YMa3jzx-QFURB-G@F2&W!qE8-p)uN=N5 zTsxJ%5+Tz|9zdLFE<&_v*oDbb&xO#uF)ae)&*{ky{p$+Q~>v2Hz_CUI<0rRhGvXQFTGd3TN;Sz@o|NXY$+*s z8638ONZCNmtn!x8bZsY2W43Fv8ulIvubx6oC!4{Bvu>`4mU)xTWCnp{N+&|QF(M+l zuLh-zX8wEo<6|Ogn}25Yw9wT5xHqQ?iS=x2#(%z_?@Pj(SHN_)VC-Tikph%9FziR& z?m##=WXX^7UXyXJa(|?iTG%zTT$5%Z<~GRKSw0K2E;;elp)aI`i)wf_QK0_~!>P?p z`vWCv4w9jg=2n&kRkRstfeR(7BG+)y@NUXJdjyqCH}l>GU{ME05k5o&v}HCY9gs)^@$ zkG_RRq4_@1-hgNSlzFtywffqZTTmff6*eC6k3tfQ*YD5Fb$R0|rqP+)hUaJ?p(B~*H84*NZ zWZL~L!3T)GcN&hFIKs@453XL5{#au73o#>$U9fd8HfcZYr2?#+xT7|9xVtTVAGB-Q zVEvKA;t;vTyYpww;3678xw7vO*U{FxEQCU<_NgN-@)BOe1q#s3c79Y*$+?svMY3F$ zAi19812gGpv9KW=7($uSF+}y0IH>$eEplt;N?K2qPm0iXRm#1SR_D6lM z{&U929pv>fe?*_M=@5NrC;VHI`HDS~osNu))@0Rhb92d`%hIs`F2>F-i`p%NDZCF) z@_v$vI%1h0Dn(g@)$+xmzYBl-$V9m13v4C&`7%#SpO0&-Av=trPF~~4kOYT}Qk6u~ z5ND=3TuFY6G;5*|*P(UwS;0^lI8>PrsVqaVJxWy=upAXU&MppFqrqrJL$QgmFG`S>gz$YsxkH)Tv-&Vg zYD*hb1XDBv~P}=M}qULNI z4&8og`2j%)Af#N%CFTb*jvs&MT7{@&4&HgeFTIOTCG#buVl~CAexRp_=U2v(UME9lVud(1P~h-S0|ZbA^(O<$UKwA6zfyj8PcGQkVm#TccCbEs3fd%=mP1oKgISYMU@q7 zyU1_n@zH9P1`(RIf@OrV-!o_D!HfUQ?^kUu+u}-|RtzFFWX)1-t^#f0qdNEm7WoR@ z(lInvq&esU&eKI2z!ppvxU;cq^+L*XAb6%Me7ezj zW-WZ0(Rrp1@B%pIEqtVDZ?y7mp-R+B3B)2jwb4G>h7&Irl}ie;=wBu`5q3oT^xw1V z6YWD(u}Pgb0|Lcg{^$@y|1!G; z9D5C2CQmp1X>sL~fN9bvs@P%i%$(xgu>bK3EqEPT&{k{7xC$ylVAXeqS7Vay=5xf+ za z?oxilr<*`6bj$SJqvVWJ-%bG+u!;jb+scgXp)A1@GqDR zmon%#8{hnEb=(J1RGpQRt?R6$X)uLaTPOxM_JI58W5T;@N!aJ(;5`zwdxa zY8_y#{!+9Tm+jzs0vptl(x3HE7w7T82VSc%>`UHwnp5O@mpVd1OQ-^ zQGwx~$W+PZ=dhO)J|0{CVEu^bp|8svCZZ_pNm;2>s#~g7k3*A;Nf2C z{?rIdN9pwHSEpV2xmZqix1R#1F6uK><+IKTGgMdcm}!yg{85L>S+r#cCURK{WV+rA zXdIkhAVqQuR6IK%o`7mJF+VgsDgiaa>@rN*$i?&W06GUD7mdRzDEF8|wP^xf5iOdv z5p~N=`#xG<#=T#+9zqQ&p1iRXj(UV(KMpEGHPnssn?i5dC0qsj{@~_$W&MQ4&Fc#P zy7<+YijTnZN4ag^tmfA$Gb=Jzkn6Q2yfPhr*c?8i)Yz1U4`ww#m|7N8UJ;)JOPlebVxeI@?B#Zjpq}Qw3t>LC%&-#`!XWUs{N)!&PW%^BZ>7 z)prjfLw40Ha{zi=F~liU}4Df=WH ztmj2DU-d*UkA8*ldvOam;)d9$*HNiq;^<>U`>%c;{z(Z{HJ$uKIGOL(+mk)8Op3^a zd>+{zy!bRiM;p(L7*w<#VuSUu(_lnBr+G(u$09-HZUsQ37yaw})kaJJ!+Oz{PB>Eb zc3?VX`ct1RFL<3Fy7yqFTTZ7Z;5klNyW?RNT3XisJS!C^E;51++XZUAe(OHy>JMHn z@MtjwN;4cQ5$MVZlERNG`IcP7bi|NTS7eI{KW}02A+c$%3dei8x!nZt(-0UZFq68%CoQ&H zrU>YKF#qoO9O=P#-&pQgJ>+>OmaF#-16cgE9<3TS7lzv#Qjzqe|rSzB=5oL#PCg_BXkI9(>159;A{Jzy!t5LGv&} zaxwy-NHqxtz@!e&)eJL-X4yz6LMyIz5Ec_c1_YM4$h|PC`gk(9ivqrjQVYs*9xt;* zXpA-aAgbc#GFPHpR95`i(@p67Ku+wCKj`jp@Mt45tl9`IweVd7P<#n=2(&m6r4U4`N7KZ|41%=)7PuMug>26=kt3zCgVPw+ zLXk)VP_J@8j+f$>{B1h`BIv1aGF(W7F5#;?tV}TqTM%?!P#kXj;dp{#((t6;;mHz6 z0%Y%IqthWFG(y{=o|!S1Oa$@2pI%OP3pWbG{S~XJ6s&wkn06VKxk>{k%;BVwV-0^1 zG07p?)BR|2x#%XCqL<|KaU{1~9 zCV3RI%!-lbTNc;F4DzRRMkL9stuj|LtwJ}lt@O0@^xh1zObLYXOF17)OJs(miJz`W zBHvCx$)fl8>R) zF5_f95fB&LqBa6Ys4_!S0t2r^L4I(Gf1<`~x`!H7o3;f(l~suW8*$bVuR#g;C)CK#-{(w$s|CZW_OCS|y7Fi#!l% zjP|A>xOsGhY`f0guhR1*OgjO}Q;*{RoGv)!Qc?QIwr_cxFGDw-W6RT2dOq&4`8^EV_c zlg{jjaxGX>*oC8!kzMy_1JvtB`0PnIVf&d5kcB5K*)^YEHVss=K1zdZx~CbD4#0Tx zKA!de>{j)^O4z9h$55{u`;4vfWmi4Ht96$DIvn_AZ`!Ev`HKMe!0cxbl&3;#h6(T*FQ_7+~bD?%|LesQDW|L@mII9 z5e*|kL((M8X^kj}u3DEg;50$;X-mVGT~IHT6$f)n{TT(wVat3*I+hhMcBsCvbLPiZ z{4_Y>EaVwU%cLk#z#p{w=PbnB6Ds`rR1YPO)GLPO;yeFf_t(W%fP~=B(V;&{=sUoM z#o^&aa(YT^Ea@#w)HdLwwSjl)C0k6PQSX(py8q&?kH)iZfzRRG3DREk1msQSVp*1= z!B8`4*Bvi=l&~}DS=RLE)Z-boP7jhS)m`)Q?^EfiB$^_70p(SFY*{cVDnx72ntARrVzLkVn1<{$ZeXP|Cp{Vj%~sBo zq`tb9)$)zG&8xxwtgrh{t3EjD_lSr?Ct9BpL>X2_+_-qW0s2G>YGrb(G&}bps~o*1 z83Vi*?ct>hnT-Y8LL2QznBOcZz1ziUcBC2nbu~9(gdpsz>1IN+SWayP^(`c^)qK*Y@Kbeb`J~Qpg~_zPC`w&55lQW`9guije%Cl zed0n2tp~emg`)D5s0-7^XI5!NvE`IXWiPT&{kCR;HYk0?UUlyz^5<1q-!}gVv3=#M z2X(GN?DihE&Io1$aF9YY1V08q@xS(k@GZG8oPxRlPD= z>U50qR^xm_m~h^{=VYhJME)L6$cg0$7fGloaK~fl4QaNTR^i3&%ClPMN(T1Lxcru| zbpXEl0)WtD2lZrUTQ;DV<)Ij%OSVimFtJOMgk^bTh;z4H#CqbdXgNiy-=i|9z@IO0 z0kGu@UTk=yyLn~DYkaj`aD+LnJVtO)uiMo5Jf__p%_qOB;0M%)&blf2Z9Rn;vM{~A zdl77TUyrYA^|%7>zlDxz>bGI?_DY44GJe)(uN7idF?iUBYuY={o7gr&BC)EcYjp0I zkEOXKwI&5fWtLPf!6~bfMmIiUNHLN*A7_`pGfzbp?MSB;LE6wDEC_d?ovT7rP=2}H z6#SnoZ@YSIllK5|%pv~Z`=CUsis0ovq$;fNpUg0m`^jb=G(NcjlJw!AC02qIe#E;V zXHb$ZqRoFJt+A_r9%eux-j5(}0~}yYDhX!O92DWsdqfu94P+PauOxB5iO}X>rQJbl zOTr>3;_HC;uXBJGJSfhqLxK07)=%dZr{?{p)?ILA-ZgWEy98d)@P7wQr#oC5kTAfn zPb8Q?16)LS;PD|y{a7zSjQp?lfO18Y`6{S=drv-Qw$WGk({sy(v2zlOLG0>ER{QYS(sYn;z>t>DM{`X=k&WV}+yFNXBcxuoO0zAH{;o=EWCAJV=Y`{}*Na)pEa-k`uGp3Zx* zT!ZlWy#k6IDIOf+|Bo%xDMZ};{&AX7Ndw-`VF@JBdq0Or7*F}Vn2JpF^SvmkPipvH z?6M_!`8TK26VTH32>Lnd{sCMk2@t^oGrgff@Reo~nD@#ZGsO1r|E!W6{~0r71)1v( z6a94>@hd?iY0A#Q7kdA;m})p;?=J-Ll}P0Mwm!n(2EOlw-X>~zZ}Tk`H}>DZ(~2NG zlpk~hN+8b*YT#BcDpk{<0*>sz2T_v0P%40aaw(890}p8U69xl#a!rB&u>A|J0|_&7 z2fB)JkWN`p4Qkjjkr)~npc9H?5(tbxLMAN6rCiXN%n%yK_MYI}!L}@RTE%^`jou*^ z`kRVVR;JhCsk_GK3nJG!GsZt>ZimlS6w2v8?-rODlPrx@%R!S!} z3ZFFAK+}u2cC{0V@jUkkixXoxLzEe^R9GDW>~L-} zma3;B?VR8e!CMCaydu|o#c&zqkW)by0n&S}&WK*KIr8*EQq)mt~A}I-LF+S1Qqh7~Db^+`A?&8es9aWU+ zWItdQ61tDVkpdI!k!{p*sAfWUQbeXvR#~|76vilO6%xv*)`8%Dx^YN9Lwlo&9nNsKFnpH5D0q91})v%(1M`v-4#HvZ)r7N zAxr+3TQ|a?>0vaX>4%?v4Z*7cC8B;m4R9%Hh3&kkJPErHjNAE>I*`aT5c)|2KWoiT zRBq?ddv7IG-s>amq&5S@itdm4t`sk%pM0qr8Uk~(Z3r2loLf(>ljOsxM4XvhIfGT> z(gp*1v)&K~N`Kb{HgO$PqMNINpl0V2*_ve7OqZpZhSP|T;g(M}23$E+41KyBgn*BK zxpg3ml~rS1>spZ1SZ@g=p$r!CZo`N#bYQhUJa-+wtcK<4`p#=3X-b(`I>x=`jgK5M zXn(6X;FYysTe>J_LaTu}B5iQ}UM9L#D^?AGS6tsvF3oq{%*JH}XDoeHn+%*zSfU_;@+AuKu~^ubpdy9YkmZ#O$_%q6C5 zznb}e;F6uX`Q?=`)=hk4eu%7CD{!o~L27A9@${Scv+pT>+_`<%nZtmb4uG_wt}POL z1UpwKf85{cx#$*-$SeJY64~*&_VDR6<-S;^Y%L-Jrqp|?`cbD%D2;QmRh&;qn5)So zlnGDsVA@q$22Gwvxig?IfOXZc@VBOb1Y4q%dRFMvuf`*??R%Dv1Ql5|1>`iPZEE(_ z+sWb_%T%QCiqTA6cuqEtH$bR(@Gy`)&@$T4;p*d?Km+5Lm>I9j(<=n@M#ith(0KWA znNm82;DMu!%jm)pAN;VT3GB!cJfHh5$rxFDQ?1me{I+CU#>&m*GEcaJk!WpQh6`lj_=%~DX7Zt#4g)}CrYlA*!UeN) ziKdN_nsD%qB?RvVwdLIi!sh-3EHXZcp`7;3Of#~7TVMa z*^An{X>u|0szRCUr7QsB3_sczfhrr+8#h+)2&bw~md4+di5&7?8lmEQoo1qt&Z3`5 z^FCI7=lK2>orSJVbY26#`DM`7A%}+jDcxTb{;XDdVGUQOE_iD*$B#0(HbR5)7waGe zlIj#*0c+INwv@sZJdAuT4h{$Dkx=Kdg_h{Vi$|d4r3RxQmQ&}$x!CgmX;1!U#56S6t_+gN^8C+iYl_%Ks%Q=SVoH%Kk?p-Fl zw*}Z3kShEwrE3acZD;Z&{e?77Q)6wScU!qvqDft_4&HO{Tv!`yaEeV5|4`h+LQKK% z}ha%A(r=Mnlkf1GHdJcV!gjG0FP@LvCi zDzJE1_k;@?G~1(tdi?(bt2M1~;|aZY>L)J*{|zuAZU|A{$4QLGB+0P<_+pG^;_xAZ zy6{#Y3oHy8FzXj2EGVtX#?;Ws^nY!v1{8MxQfMiJ&8T4I8yFbhDfULfpu}1@`_YIF ziR%C7VwJ#sh0TUX41rzPR`w->M^$&t>D5)n{!pf{AB}>810^mu*Sj+AMO1XFGmbUh zL$ocI)Z7w4BoIu=3%H2(sh%Ot_((1<-K~<%%^ur2A5@v?-ao{+6;#w#1 zG0(1euhXxu=agY0!FAIK=sNO=<)*jPJEGJI1Kq`Owkzb~UknMAwPj_#l}0p%=W8ud zdT8*o&6RT=&{z_}mOr}v;`|YZ;aDrmKEO;}PM!#;9f>Q9Wl2=MOzwNIAp9vYTurAG z8n^2O8#f5YJ2yfTKdz4*_0}PnqoxcpU;3-ETy7N>kcX}O0dGkt`3Z$v%ma)h9}E;K zgd!)4B>Q~{$Iur!%{**k+W7^>P_h-#ImUK1VEZldqst*-&o-%5OZ?9qzu(33VDaI# z)v*B8PldNNu%+%l_`jGX?8#7$B+6eg$IH0hP)b#DjXJk zGiu-TNh$(N2#r<0A^5AQvB&Yu`Jo0fEyueqV)xMG92qU}Ii}r2O1jXH+3_}0twv*T z>8v;C>7saCDlofwU#%T)PJr;tUZ*Wh6LNsDgCoMU02?=-^Uqw@e*0%elzds`bBJYS z-A?2APkTB$B~mjCI@b>|Ua+(DgrS@*~Cxe+}Zvx%btVuPs>B#SNj zj1Ol1*2T>oco2mA!ySbM7bl-z>nqcP&{pYq7QR$(J1m5n|60BRA6%!WkDkY~2b}&1 zh`}ct$KTM?m{1y%a}d(`)MSJaBiMwAprxT+X-+~hSdc=zaS2f)W)}c%ShX7DwWG0X zUs+DXi3zS@6%NPTREe1z5jkrfMRnrm#OJ&875xVm^rN*Q?=y)n`q0$X8B%DzL|WTb zKMEem*UD^ux>fk+vO37u>LijX36KslMBo*42#_aMak1BND-7R6IG?WxdW*%ZtTI`B z_$idoz5Rd)fm9QDUKV*y&5@x>%x7PRjPF)J*WTg<)5BNG&^(!Nb0%XN8P~GT4^f9- z$_l+U4mHo8q{Z>0-|E2vpZBW+nQ~vyMGv*UR#;k)6Pa4$rYO2LqaORg|g_9mAB8SQZd{@Y3+K<{IZUXw9V_oMgw>1!Sv=JGf`xU{ld1o!_8@? z#nq5v@@w$W+4EIR*VOyYlIA#7zPz}*yLai@gjO`&OyPA}MvnEgcQ5Paym9VPKXI}e zU+HDc4a3s%V-O9|tIXBX0>Fd(yJ9?_kwyv4C*&zr7+YkE-!qm=cFHFPnDe*(y+XpT z;X6bNV@}zRRfo>gPebkFL%PP6td0vt1-b{&0=D(xQ;aU;JShgq9IV^gbPUWcM7{Ni zYZ4)jI&;oY>^)GkYL5n=Q=U0hFP4ARa_xRJD~0;Q&Z$nw?>#QcmkS`MOhk9;Br(6M zBf6mZj^g~{&JOxq$9T!d?a{GZ(mivODpr2p+8Wz4H(QXwwep}6cF*p zQ2Iuil-OmH7+M<9|Bl?qE(xIh(S2z;pr6eiKcuhwy&1{%HW~BHcFOwj_9(+uTt(VB zY2WV6ef7c`kTC~i ztxFoOuu7UZIv-XrQ+{a1zV0Z*V=wP)dzRk1??~{`);g#LQrHldZkH4qb3A-_uAz@7 zaP&V!vsq@Jlhn<0d1|*E2w|PO*+({3mdC!oSEG4m&vYqrS za{J@{kt=+rKW$F&TB5&~Ec#=dr4-u$^?9? zm(YE>nVH@6R|6ze5$R%<6Sdn*+=?0hv1-^*Y1D9*MY7-rBYZ;3+yWe@xG=htC%K33 zBMmT|XAu?O&ECOWM5&*TkLn(0xd>0{LDTlqjs>UXLOk;ISyB<9J<0(YFBDHjr2-}3 z?)%(XyOL@Vq}xIo2JT_rNQ?H@sS#_iC*#X6v`x~SW^6**42 z5@7NHxzScx7sBLrT>OD_tzX9@wRq`9*cyfjBLez&Fgkd}_=mU4>YBNB|8%AI4A!<# zbm~{&!U*8VqlnKrM{Pc}{`#q zj(nd#n<$Ym{u_bPFXL6P0nMM~Q2sHe1Xwyb*ccj{+M3!q|J%Q+oqo$3!gyie@7H}3 zVMDx=qbQMS{{khta+Cn6CDh1KQo#Vpkb*=6&tAJb%O{sf5?#%d?<_8FPhvz~39Opw>_|-$Ev?>Q@Zk7YpSA zPE(QBpv{BxUOFob^s*>rmF&CnO7f#vlD|k)vz5B$Ua%nqc98?@@1{~8<6{1#Tt8p{ z6@3XX0RJFR`2+gJRg|fMbipQTIH7_QVuF+sq?6SKNsG5Xy6Vd*6p(#tNEEqZMjLTG zQ8?ijytu7YRs30&4B2)p1>etpAg)Og$xjb;i!nkgw97I9Z$*-yh@m93gG<^sgtdaE z);tvmV$<}?2q>o2N5afWh|Rh-^XK@|muvy93U5nGXT-Y<#(XZ;(l*y`us7ZJTijO7 zICYpDV*U3fFbTT|V3=L0IIq2#3GmD_x_1_?yZgh~W(G6N>$8y)>pt8uUnidj9_KLC z!AbJTZKizb#_`zGh;JFs&?Z2Iz~}OV%ewl|3$Cv2v0@A9z6y7SB$r|ydHJh-AB_+| zkDh@?$enNoeVxM0*5Rjp9d_7bb2hG%1r|<5p7u1~x2tT1_YX4F_{)da#dJ9XBfYlF zu()OfPKc~0u(VuGXs|kbx9#z+7;g1$m)|vuK|Ie%^PGmLAA)znGws{ds5t#hn=? zx%8~!c)1khSa8-1qBJKrch)+du@TfkQtnY<-=G2=z4`B3zQyx`919-lH!Inc+>P%E zk*>R09os6(-3SVBW%oT1K)_TLQ|D$Pw)FcUt2t)MmM!BQ4gY|@z*GRcz`-F@$l8|& z1}A!nGDea$rz{XLb+za(F_nwuy#1Y+igTB$t=<6b3sLAZ80L!yGAy`mOi2iuZ*J(~ zrTE<|59&*Gb{rEVw1!8dY7f3~<7aj$SF!RuF=METlhoxZ0WlV(8>D-SJyI+IuMdO2 zqDQZutE>V+I>R*5BB)m4tKvRtoWkluPJ40k!^Y+9NVMr5`S4^Tigjm+5GMhAyCc)^ z-}qJCrJgB@Cl^D57>>uqFJ9dE^?0o#2Vm)s?v3Wv9o|4um-i1P2 z5F@s4eLIvbSNLl5rDElpK%h}*DRR6X=Hee!B9WN>r+h-i&AXW-cCp~_v0(PK%|tjnTp8zuhx07 z7qZ8t7(h_;d7^hkr1OE<2H;t9Yo|#_cR!{>SUz0$QFVORSd&lHp*{=uuwpyzFGdv} z;)q@KFGe*ZDe~cK0=#c?K)E1`QiB??*w9yc?O^#hFr~~5JwdW#8J(t^H0T%K;5`p9I+l>f- z`pLrGU7*|Qx=8Sul;-HUyTi23PMI@b3o^ZauGUpTWuo&-1KcRHvX*|4SIVBazT1`O z7Y@tl`6f6QZjC9WT>CoZ0HW$kU;X`F>BzQta5tp8dk%i*09XC8rJRH{Z5R6Wd}BwY z!PopKpTHL%f`~7Juhs-!vo(OSs7ZVJ>C4CbsNeBCnRqAX#}DNle3m{0lf^raD?FWu zZ~x0sJskNzj+*N>4%>S)cvqOT2>zc)yT@;8J}J<=5cw0Z1_orO2p|I4?rrJWaFrDcnz}AwfsCDj zF~1J;)8Q!h{!nup2Vu*l= zQoV7Y*kSCRbZ5Be)v?Dz$?NHcYCG&wdLlXbc%n+E68b&qa`TlKB%U~5RT=jr^%!ZX ztgxemsU8*riTb`HCT27u2ZOw4Xc;fK)oa=UhPL!Iwcby>6=oWG$O>^l?0_l-sTS6w z5B^q8D*|0guxTbSjbo#TNG-Klff8*&?jO3eovc9Q`nW68K+9ONyLv{tKINe95w+OV zC$(@qUNOxmF<3MaYEkfbo08Md5j@qKZn57TX~TQ29X1;ifzZggkyb*_GpMofZr1c8 zSR8CLHt_DD%e$yF)JSvy#XdtNy9nZl!N!%I`rPzTjnY~v%tDbuf@jG4=WZ^%Qqu2H za)_?B!X((H{7f=`Z5s?gwhifGn1-s%AlrsJtYE-blwhcD*W5Z&JkF}l#sTSKH zBR+&ef?4Bz)*uM^B-=sGH}`=igXh zy3ISWr;jG`5*ithnNBY5 zYUynvnj4Si9RkMET07-oqZlIb0o;x0vR>>TpdTonMlvCH^)+@_A}f>^>QLi$riUm& zQ_rVQHB0D=ya-fari~Q%Ubi4a)7EO4KYX zMYX_zfvxrR)=VnYUK))gJcd)0(y#P527%}LUS9kaq_sQ+n`TzVH4DafFawGkeQbYD zS2?5R*nq1|_H)Z&I&C+TkyQ=54VUsn!w0txYN|#(T-tFEM?T53BDU0SE2?=+{C5u0 za{%#qsXNcET6PH5##*felvaP8>}Xr4l9{MMlyZZ8SqkTwF~Y-`^kD`K--*FEZMBRfLEtQ;kSUpz?WuRQI4VnD2V zXhP{n=ui10klS*t>xz;2Z|=qTr@3l2DqglpPeK(bFC4aslQ0`%pFNwaxH4lG_W`Wy z2$s-4PxSSEF~i}U?1si751#r3^ZclnhD%PWt?C9dsNo$=di(jo`D^%*jFPzY3)`#Z z*F6EsC>zroc`LOIqBrtWYs!MEaJbn|ymMt|;mYU9!Rl2$MG&3j_=N;~X#8Xn(m9~BjA!lfC5pG%-FI|6R-xB4vv zUL#B!SO{qt>u<)!Ss$_CL!x5Oj|uhL0Si4|M?4f%A`Q$e#+`!MxWYsLH|?5(ElQU3 zFx5aUsKUtdMGp!!*l+qlbzR2*2LepPQsqaeCIugtW%KxQTMl$TTOY1Wc`H*Dh+VqP z7DR`E;mtJV%_q(7YME~R*2~eOD(A2Suk@*-sYI{Otv&+_mdQ`a25X`c1xV}WE1W(qayy6Rw!LM zV}+q~Tzq!m#+ANCrZCe&FECg(&+7Iq;Fs67_S#ggr{8n;>%E~q5=`(qTivh-?Y%f_V zTc`5tb%|yQ2bhiX-rL5?WlV*+>u9jT`-f#lrCX*}2rViSO4=)<4!xE0g6D9FhHcK|Ac2cd+@dkyvXeKSMfAYQj#5~4%$hJyT^jc%1b_E!{ z)_r_OV)QsW_0k#g=}ucYn)p)~^F`x1cV_MCyUt#){%7tVHjYF09&zt>A^Fdc7~Kx{ zKZ=BwIML2~@ICW|5bAwR9(j^b@O_XJ+C@D6K1fpX!xwrlDn#QUz8Bqc@ZPnKC3iPd z+@P_UA@E}@E{M3hjSmS#=>@@mlb7*Pn$Q#Q+5T;_!H=K?`QMZn0dJE3?3x{6N&W-b z9=G6<{_C+wj|nHG0!kgwqW$oJ0+{VihymQ-#76_1YQ210;r#Tr;u{|MmTRQ-YGM8@ zzON;ZV%bRYlWN?zqhk{uRH$K_2h~sYJD=|j&v4E@{xNDo2q2}9jXI^w_*0oKEe9U4 zw(;s(LkxS`wHgd`_}ROQ8-U+O0V61FUu)n?<2TMWK}Lv>Oo5{jIN^2@-eCFR<(Ph# zy$ebb022b^B?%)5!*jDlKAik;DySLLoe+q(8z4y!gG_k8LoT-u2GNvUtslPe$^f1f z%R`1JTslg!^LeuJ!P#(ROL;aHDqaLq8j(IzB-RPmXegfay2U01l4aBm)+*uHfgn^? zX!eGS2GTMt&XQTwI$snf$x+G!6H4TQCSUU#07LFlLWh;aGMR!T?o*!=Ie8{DJ2fzn zlu<99r}a)PdoN~;R?at|Q&OC9il_&b&Qjc}5*JY(+oI?FNfIIR&Ba8N?+lWzS0k8#x|eOhlz~>%)t<@d0<)H z0r_o*a=oJ@D7#-jg=zLtoF-=_dsY5EQZ3CzpkoCyQ%8c&plP7ejAFJk_(@YWRRQVF z*RS@4=6iLnm;<$@D3Wqt#33BpiA8a|*xs<5&i}{ORX|nsG;w*4&iCk!`vgQluv6tS=X6?F_013Lf(8wI zY(74{!LvpioJ`Fsxm0hxZ(rNo1{o#m;`$Vf%FpSL`*qd;#e-zWpZAJZgx1-g*FMgo z-j|n0vo20@{`7jv%`v_GXN5*MO-dSD?Mp<&t*X5p_XjzR>S*GZR}%Jg*-oQ9(+|!6 zVO`EJbO0>9J^^*I!Svw7OKAZHs!sP1t)$0cxj7saFyYGp`lb>1fy2d?Dv~3!h z`su=zS_dBFIPQM3F!^(+o?Wx!lb!A@yq)#(WJ!KgGm{rhS}Ynkba%qe@1?fSGF=Xw z%&QZWkW&ymv#@A>oYUxlKCX3VU;ONY6PDEu4Bm5pNnmul7x#*my>)nbcW3&@*DLDv zEH>WNVc3G8*C&6bWDRdsYscEb^)60$+T%;6`{&QEzqVYabW$dacmMn)cv7OgZm#0>U?fS)!8OC7Mq^58fy}gJ@0soNnF^F)t`4%AAPIpmYZ=N?cVv` zj0p4hCGG83KE){CB(+H#f{fS8OZFx{y%D}Wzn;$em`HW3`+S4PJu5G-ICItNbw^gX z|Gewb8~ZlcdQa#<7-&n$JC~dRXleVlGVAwBbJV@mVLR9 zzjw#pl!)J}91AZWO1!2zw8Xsvd0U=55H}~swbPS9TT{~w+TUw+I&1o;n=6)8OLwo6 z8@{FfNuQ(LJLhy<8d4*Fedl|Nn^imgs<_d)iQ5vV*6Ce*E{{AuSPrkUcAYsk-nI`i zI`r6MM1{O18&5xO9c(%D^oBFd0^9Xi@GQehb6{_ceerjywpgZRXt;dM;~tX|TnAKM zd~#C-x*g}db7`xtuj+Ws$XnF4cIwB7MHX{T7ri<#aeUPGJNList32`D=itKo_Gfm? z(4Y6pdiIi&10LF@9kV5c``1XJLCJQ&dMttL+b{44?DJ3 z*VE>8Pd(4IO{PXY9X9iK+SBw7D+8?~AE%Fe)n~Uu?DP|*+=F{Z&Nmv}zIpt6KZlDE z&!4JqR)2B4)zM6?xDU?l+jlQ1{yp8ITgCqty@a7xpn%&pAA+&4yt));k*#q^tfX} zT%+;r`&5~(omeY($Jo>ck0;$o-S_Ffc}n_^je)(?jpq!`KUAr)d4t&6zbC{U8vg#? z{Y~BUUzPrNbL`8#mAB*aZhQ}kd6yG2JmJJg`}BK3I%=cOyPmv%+2y`&yvrQzzGVyEWlck#b0Y03cou9c`|At3A^;Sm=$eC9A$jKV(O7^)vba~-< zYV7B2t#&V}ynUCiaidX}2I;IC8KUa-%5CR~A8|`2giflzIrC_G#C6lBu?5jl1*3dE zCVZ%RVZ!Q%@xS!?jSY&uP_Q&>>z-3pf9mynlZD?j9B;6#y=9PjLhb9Do=!bn@u<7$ z`sD4`Dmi`s(S7CTkE@rL{51O7aqX|8xJ2dZxS{8kfBUQ(7>|3oyl*-zymadAD%H$y zV_szS`22I<-G^}x+Rtlc`|VMJPr>z(v+7;gY+C)BXa0Y&dG=$r4oHq05f!y1zCjf( zv&F6KoGw$Y-8Ai4uhHqz25*8N)PHWbDx>b5kXI(A_gfcVpr2!WoIQ#icXsdoe%JcW zJ@*dt-7;}ogYlay?%gxR9rxy3U(|ZR#rk)4X(g?EJZeVA4lWIf3w&nBRUJI7`_${D zXFk7NW_Bue^!qm}dya9^7+c^JH049_^<@{^RK7W}{)I~p-TZ&Ar>ZVz4!-*7(K|G0%<1Xl^K=?V^fblS4`N7Zkatmk+y*t-A5m9@j}H!N}eyshm# z=R$W6w<8w4;_n`O=YEj0S?@ifyBr%pfrVB?Uvd)q9BlvXD*vTwXKbqdqXN^9zMrM=$T53yPGvh%ds z74O=3+T+LLId*r4ZJXcHC~QWUPSl2O2h=;%BgSMD%*u&B$}Nj~)M(H7?Zdk5o|rVC z=bbG})8~Eb`g4s&4Zz1n|;VEtnsLDOuFfoXHU=Otg3i_ z;i?+zlEe2$3|+FNOMFR$y3@4dae4P2Z`ilwba9{fZb6w{E({wwA^cY#kL8v0xChVT zSG&b!x3Y_Cu?c^~PmiKYH_gl1S2eZL0B)BEq4ma}=e)n?ClgVwdK|0oHrW0_X1cZU}1e{6jiK4hLtpuRRKjD{*RK$O6lbb4o~v%6#$Uh2C}ti- zE>3NlFrMqA0&}}W6;i0BUX(?)kPj+ z)mW~UqGx5HYGP$mdLN6bQ+%ZYJqno2HBwyj7pkwC%r#ULR~KHsPv&ZA-6a1hTxZ4f zPD0uGDS$V*tI#~Ns}a2{gxbURM8}||FH11Z%7wJsr zDud7d)4BeNpBqu+PsdTDIGCMsIop!7XW;KQ*(oD)tf@Kv)^ekfGq@I7z1V+FbYlir zMQb_#cZ%sA1M;4UD)*#!JDShlZE5dJuDW)k!#L4-X$EIaz0yIR-0_^L_7GO)IFoar zz*(HL7E!-hTuViRd|H#hxzL$eTvf%OW5SC=0$%2v;9pV>pU|VBbv4E`H37|9P+9^P zqE(5C@t@-2SysoHo+P2G39~^8yB8^Ii>+wOY%V~N_7Z<{WHJY`Hm?|eH=@aNFvb(# z@V5sQpj=CD>0GY2Rsn_1p-8sMr;%W7z;O#VpCf*M*>TvN+|(&lpw zly_?KZ*KH^KA`Wb$G=%owIvu%-$c${xxSIu;etd|9}pnEB?V}y$h(6;4{cH=arRoL z$T^AYsI`bjCUIR9=FP|@iL<3gNnCZs&X&|KnX@OqWX?~^iuxu4Yj?^>=GtnFrjlf? zt5yT*v;hBUlh#7$@Zkkq6C@7e?@r2=J+-KBPp!)IUlN#ju$Pv~=+9_&)AohjK&|nl zUIeS+N8yXO9$EwG$Ra3I%}B~y#5zrZr8yTRy!?#PGN1)1pnr?eLdp2i7z)%|B-fV| z3}qmx7lW~f$5QTM&Xsn20!3jt#42kSqsn4Bw3zFzI5wVDaby&$qgXVNz1ULTL@j-q zzXTNhG)aq$Vzj(y=ufG2-*o)-YY8mYm8rCFIoeiU3UrL)g_lP0GISO#g*c6wCVV@) z6t<&B0()^?I#)}Fsu0Z7**Q{y8O^f(HkZSF9AtfYU;2I-7QZR zN(z!ua%4FuduSPYdbU6)c37xoMzM2IY_lB2$%|MqN2eA6xo-1OJQl@TMYLc!*FzD% zgnf0P4yjstl)D7F@3I12TwnTE@wmCrjXTS<{x)D&mi<-1bU6^Y!`k_-_^a4wC09es zp2AkbT8v&*_Q8(Q$Y3bzfy%jQ*FT}9MJ;YG2UtESkzNqD)xNy~`(tp?ENn}w2XtD)hIwhAxC zX}~ps0@END|7{n_oOhtf(2o-HujBV-pxN)!xQ>b;8C0Ccxlvk%mLWy00n}SrLL-x1 zpy6p&V!m4_X|WsB;rUTxE%2V5P5J8}n9*y&|M7c-m-qW2+LzWs4lnQht3p@|$8}TmJS56@NY~6u(;!l3vUcUYe!@Potyk#gV2S1)gitF}n7DO5Dk014;@`{#B>X1`xOY znZHWLoq^|oiYnTBUM5Nz=l`lzgl|Hvu@_~vMqK=>R^%qkUI#7;(yF2t1+uCS3;wNY zvk3xs?y|f%NKxx5g>J^E3N``#X#T~6wqFGXurexgzb+%G6ZPKA4baM`yva(x*l)H^