Skip to content

Commit 4345901

Browse files
feat(nm): Modem autoreconnection (#5762)
* First (shocking) implementation of modem reconnection Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Refactor and test fixes Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Added tests Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Updated web ui messages Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Updated web ui japanese messages Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Updated web ui default values Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Fixed core.net tests Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Fixed configuration.net tests Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Use NMDbusConnector for managing modem reset and autoconnection Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Changed method name Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Refactor modem task handlers Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Fixed tests Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Added check on connection status Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Removed commented code; fixed copyright Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Minor fixes Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Minor fixes again Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Minor fixes; managed modem unplug Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> * Updated tooltip for modem reconnections Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com> --------- Signed-off-by: pierantoniomerlino <pierantonio.merlino@eurotech.com>
1 parent 02ee075 commit 4345901

21 files changed

Lines changed: 971 additions & 519 deletions

File tree

kura/org.eclipse.kura.net.configuration/src/main/java/org/eclipse/kura/net/configuration/NetworkConfigurationConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public final class NetworkConfigurationConstants {
2525

2626
// Modem properties default values
2727
public static final boolean DEFAULT_MODEM_PERSIST_VALUE = true;
28-
public static final int DEFAULT_MODEM_HOLDOFF_VALUE = 1;
28+
public static final int DEFAULT_MODEM_HOLDOFF_VALUE = 30;
2929
public static final int DEFAULT_MODEM_MAXFAIL_VALUE = 5;
3030
public static final int DEFAULT_MODEM_RESET_TIMEOUT_VALUE = 5;
3131
public static final int DEFAULT_MODEM_LCP_ECHO_FAILURE_VALUE = 0;

kura/org.eclipse.kura.nm/src/main/java/org/eclipse/kura/nm/ModemManagerDbusWrapper.java

Lines changed: 0 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,13 @@
1414

1515
import java.util.ArrayList;
1616
import java.util.EnumSet;
17-
import java.util.HashMap;
1817
import java.util.List;
19-
import java.util.Map;
2018
import java.util.Objects;
2119
import java.util.Optional;
2220
import java.util.Set;
23-
import java.util.Timer;
2421

2522
import org.eclipse.kura.nm.enums.MMModemLocationSource;
2623
import org.eclipse.kura.nm.enums.MMModemState;
27-
import org.eclipse.kura.nm.signal.handlers.NMModemResetHandler;
28-
import org.eclipse.kura.nm.signal.handlers.NMModemResetTimerTask;
2924
import org.eclipse.kura.nm.status.SimProperties;
3025
import org.freedesktop.dbus.DBusPath;
3126
import org.freedesktop.dbus.connections.impl.DBusConnection;
@@ -50,9 +45,6 @@ public class ModemManagerDbusWrapper {
5045

5146
private final DBusConnection dbusConnection;
5247

53-
private final Map<String, NMModemResetHandler> modemHandlers = new HashMap<>();
54-
private final Map<String, MMFailedModemResetTimer> failedModemResetTimers = new HashMap<>();
55-
5648
public ModemManagerDbusWrapper(DBusConnection dbusConnection) {
5749
this.dbusConnection = dbusConnection;
5850
}
@@ -250,119 +242,4 @@ private List<Properties> getBearersPropertiesFromPaths(List<DBusPath> bearerPath
250242

251243
}
252244

253-
protected void resetHandlerEnable(String deviceId, Optional<String> modemManagerDbusPath, int delayMinutes,
254-
String networkManagerDbusPath) throws DBusException {
255-
if (!modemManagerDbusPath.isPresent()) {
256-
logger.warn("Cannot retrieve modem device for {}. Skipping modem reset monitor setup.", deviceId);
257-
return;
258-
}
259-
260-
resetHandlersDisable(deviceId);
261-
262-
Modem mmModemDevice = this.dbusConnection.getRemoteObject(MM_BUS_NAME, modemManagerDbusPath.get(), Modem.class);
263-
264-
NMModemResetHandler resetHandler = new NMModemResetHandler(networkManagerDbusPath, mmModemDevice,
265-
delayMinutes * 60L * 1000L);
266-
267-
this.modemHandlers.put(deviceId, resetHandler);
268-
this.dbusConnection.addSigHandler(org.freedesktop.networkmanager.Device.StateChanged.class, resetHandler);
269-
}
270-
271-
protected void resetHandlersDisable() {
272-
for (String deviceId : this.modemHandlers.keySet()) {
273-
resetHandlersDisable(deviceId);
274-
}
275-
this.modemHandlers.clear();
276-
}
277-
278-
protected void resetHandlersDisable(String deviceId) {
279-
if (this.modemHandlers.containsKey(deviceId)) {
280-
NMModemResetHandler handler = this.modemHandlers.get(deviceId);
281-
handler.clearTimer();
282-
try {
283-
this.dbusConnection.removeSigHandler(org.freedesktop.networkmanager.Device.StateChanged.class, handler);
284-
} catch (DBusException e) {
285-
logger.warn("Couldn't remove signal handler for: {}. Caused by:", handler.getNMDevicePath(), e);
286-
}
287-
this.modemHandlers.remove(deviceId);
288-
}
289-
}
290-
291-
protected void failedModemResetTimerSchedule(String deviceId, Optional<String> modemManagerDbusPath, int delayMinutes)
292-
throws DBusException {
293-
if (!modemManagerDbusPath.isPresent()) {
294-
logger.warn("Cannot retrieve modem device for {}. Skipping modem reset monitor setup.", deviceId);
295-
return;
296-
}
297-
298-
Modem mmModemDevice = this.dbusConnection.getRemoteObject(MM_BUS_NAME, modemManagerDbusPath.get(), Modem.class);
299-
300-
MMFailedModemResetTimer resetTimer = new MMFailedModemResetTimer(mmModemDevice, delayMinutes);
301-
resetTimer.schedule();
302-
303-
this.failedModemResetTimers.put(deviceId, resetTimer);
304-
}
305-
306-
protected void failedModemResetTimerCancel() {
307-
for (String deviceId : this.failedModemResetTimers.keySet()) {
308-
failedModemResetTimerCancel(deviceId);
309-
}
310-
this.modemHandlers.clear();
311-
}
312-
313-
protected void failedModemResetTimerCancel(String deviceId) {
314-
if (this.failedModemResetTimers.containsKey(deviceId)) {
315-
MMFailedModemResetTimer timer = this.failedModemResetTimers.get(deviceId);
316-
timer.cancel();
317-
}
318-
}
319-
320-
protected boolean isMMFailedModemResetTimerArmed(String deviceId) {
321-
return this.failedModemResetTimers.containsKey(deviceId);
322-
}
323-
324-
private class MMFailedModemResetTimerTask extends NMModemResetTimerTask {
325-
326-
public MMFailedModemResetTimerTask(Modem modem) {
327-
super(modem);
328-
}
329-
330-
@Override
331-
public void run() {
332-
try {
333-
MMModemState modemState = getMMModemState(this.getModemDbusPath());
334-
if (MMModemState.MM_MODEM_STATE_FAILED.equals(modemState)) {
335-
super.run();
336-
} else {
337-
NMModemResetTimerTask.logger.info("Modem state changed. Reset skipped.");
338-
}
339-
} catch (DBusException e) {
340-
NMModemResetTimerTask.logger.warn("Couldn't get state of modem interface, caused by:", e);
341-
}
342-
}
343-
344-
}
345-
346-
private class MMFailedModemResetTimer {
347-
348-
private final Timer timer = new Timer("FailedModemResetTimer");
349-
private final MMFailedModemResetTimerTask task;
350-
private final long delay;
351-
352-
public MMFailedModemResetTimer(Modem modem, long delayMinutes) {
353-
this.delay = delayMinutes * 60L * 1000L;
354-
this.task = new MMFailedModemResetTimerTask(modem);
355-
}
356-
357-
public void schedule() {
358-
this.timer.schedule(this.task, this.delay);
359-
}
360-
361-
public void cancel() {
362-
if (this.task != null) {
363-
this.task.cancel();
364-
}
365-
this.timer.cancel();
366-
}
367-
}
368245
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Eurotech and/or its affiliates and others
3+
*
4+
* This program and the accompanying materials are made
5+
* available under the terms of the Eclipse Public License 2.0
6+
* which is available at https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Eurotech
12+
*******************************************************************************/
13+
package org.eclipse.kura.nm;
14+
15+
import java.util.HashMap;
16+
import java.util.Map;
17+
18+
import org.eclipse.kura.nm.signal.handlers.NMModemSignalHandler;
19+
import org.freedesktop.dbus.connections.impl.DBusConnection;
20+
import org.freedesktop.dbus.exceptions.DBusException;
21+
import org.freedesktop.networkmanager.Device;
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
25+
public class ModemTaskManager {
26+
27+
private static final Logger logger = LoggerFactory.getLogger(ModemTaskManager.class);
28+
29+
private final DBusConnection dbusConnection;
30+
private final Map<String, NMModemSignalHandler> modemTaskHandlers = new HashMap<>();
31+
32+
public ModemTaskManager(DBusConnection dbusConnection) {
33+
this.dbusConnection = dbusConnection;
34+
}
35+
36+
protected void modemTaskHandlerEnable(String deviceId, Device device, NetworkProperties properties)
37+
throws DBusException {
38+
int resetDelayMinutes = properties.get(Integer.class, "net.interface.%s.config.resetTimeout", deviceId);
39+
boolean autoconnect = properties.get(Boolean.class, "net.interface.%s.config.persist", deviceId);
40+
if (isModemTaskAlreadyActivated(deviceId, resetDelayMinutes, autoconnect)) {
41+
return;
42+
}
43+
modemTaskHandlerDisable(deviceId);
44+
if (autoconnect || resetDelayMinutes > 0) {
45+
46+
logger.info("Modem {} activated. Starting monitoring task...", deviceId);
47+
ModemTaskScheduler connectionScheduler = new ModemTaskScheduler(deviceId, device, properties);
48+
if (autoconnect) {
49+
connectionScheduler.scheduleConnection();
50+
}
51+
if (resetDelayMinutes > 0) {
52+
connectionScheduler.scheduleReset();
53+
}
54+
NMModemSignalHandler modemConnectionHandler = new NMModemSignalHandler(connectionScheduler);
55+
56+
this.modemTaskHandlers.put(deviceId, modemConnectionHandler);
57+
58+
this.dbusConnection.addSigHandler(org.freedesktop.networkmanager.Device.StateChanged.class,
59+
modemConnectionHandler);
60+
}
61+
}
62+
63+
private boolean isModemTaskAlreadyActivated(String deviceId, int resetDelayMinutes, boolean autoconnect) {
64+
return isModemTaskHandlerPresent(deviceId) && (isModemTaskHandlerResetActivated(deviceId, resetDelayMinutes)
65+
|| isModemTaskHandlerAutoconnectActivated(deviceId, autoconnect));
66+
}
67+
68+
protected boolean isModemTaskHandlerPresent(String deviceId) {
69+
return this.modemTaskHandlers.containsKey(deviceId);
70+
}
71+
72+
private boolean isModemTaskHandlerResetActivated(String deviceId, int resetDelayMinutes) {
73+
return resetDelayMinutes > 0
74+
&& this.modemTaskHandlers.get(deviceId).getModemConnectionScheduler().isResetScheduled();
75+
}
76+
77+
private boolean isModemTaskHandlerAutoconnectActivated(String deviceId, boolean autoconnect) {
78+
return autoconnect
79+
&& this.modemTaskHandlers.get(deviceId).getModemConnectionScheduler().isConnectionScheduled();
80+
}
81+
82+
protected void modemTaskHandlerDisable(String deviceId) {
83+
if (this.modemTaskHandlers.containsKey(deviceId)) {
84+
NMModemSignalHandler handler = this.modemTaskHandlers.get(deviceId);
85+
handler.getModemConnectionScheduler().cancelAndShutdown();
86+
try {
87+
this.dbusConnection.removeSigHandler(org.freedesktop.networkmanager.Device.StateChanged.class, handler);
88+
} catch (DBusException e) {
89+
logger.warn("Couldn't remove signal handler for: {}. Caused by:", deviceId, e);
90+
}
91+
this.modemTaskHandlers.remove(deviceId);
92+
}
93+
}
94+
95+
protected void modemTaskHandlerDisable() {
96+
for (String deviceId : this.modemTaskHandlers.keySet()) {
97+
modemTaskHandlerDisable(deviceId);
98+
}
99+
this.modemTaskHandlers.clear();
100+
}
101+
102+
}

0 commit comments

Comments
 (0)