Skip to content

Commit

Permalink
Pass in locationprocessor to mqttprocessor so that it can publish on …
Browse files Browse the repository at this point in the history
…reconnect
  • Loading branch information
growse committed Nov 2, 2022
1 parent ca4aedf commit 8bf4426
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.owntracks.android.model.messages

import com.fasterxml.jackson.annotation.JsonProperty
import kotlin.time.Duration.Companion.milliseconds

interface MessageWithCreatedAt {
@get:JsonProperty("created_at")
Expand All @@ -16,5 +17,5 @@ interface Clock {
}

class RealClock : Clock {
override val time: Long = java.util.concurrent.TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())
override val time: Long = System.currentTimeMillis().milliseconds.inWholeSeconds
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ private void loadOutgoingMessageProcessor() {
break;
case MessageProcessorEndpointMqtt.MODE_ID:
default:
this.endpoint = new MessageProcessorEndpointMqtt(this, this.parser, this.preferences, this.scheduler, this.eventBus, this.runThingsOnOtherThreads, this.applicationContext);
this.endpoint = new MessageProcessorEndpointMqtt(this, this.parser, this.preferences, this.scheduler, this.eventBus, this.runThingsOnOtherThreads, this.applicationContext, this.locationProcessorLazy.get());

}

Expand Down Expand Up @@ -326,6 +326,10 @@ private void sendAvailableMessages() {
Timber.w("Exiting outgoingmessage loop");
}

/**
* Resets the retry backoff timer back to the initial value, because we've most likely had a
* reconnection event.
*/
public void resetMessageSleepBlock() {
if (waitFuture != null && waitFuture.cancel(false)) {
Timber.d("Resetting message send loop wait. Thread: %s", Thread.currentThread());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@

public class MessageProcessorEndpointMqtt extends MessageProcessorEndpoint implements StatefulServiceMessageProcessor, SharedPreferences.OnSharedPreferenceChangeListener {
public static final int MODE_ID = 0;
private final LocationProcessor locationProcessor;

private IMqttAsyncClient mqttClient;

Expand All @@ -78,7 +79,7 @@ public class MessageProcessorEndpointMqtt extends MessageProcessorEndpoint imple

private final Semaphore connectingLock = new Semaphore(1);

MessageProcessorEndpointMqtt(MessageProcessor messageProcessor, Parser parser, Preferences preferences, Scheduler scheduler, EventBus eventBus, RunThingsOnOtherThreads runThingsOnOtherThreads, Context applicationContext) {
MessageProcessorEndpointMqtt(MessageProcessor messageProcessor, Parser parser, Preferences preferences, Scheduler scheduler, EventBus eventBus, RunThingsOnOtherThreads runThingsOnOtherThreads, Context applicationContext, LocationProcessor locationProcessor) {
super(messageProcessor);
this.parser = parser;
this.preferences = preferences;
Expand All @@ -87,6 +88,7 @@ public class MessageProcessorEndpointMqtt extends MessageProcessorEndpoint imple
this.messageProcessor = messageProcessor;
this.runThingsOnOtherThreads = runThingsOnOtherThreads;
this.applicationContext = applicationContext;
this.locationProcessor = locationProcessor;
if (preferences != null) {
preferences.registerOnPreferenceChangedListener(this);
}
Expand Down Expand Up @@ -145,10 +147,13 @@ synchronized void sendMessage(MessageBase m) throws ConfigurationIncompleteExcep
}

private final MqttCallbackExtended iCallbackClient = new MqttCallbackExtended() {
private boolean wasConnectionLost = false;

@Override
public void connectComplete(boolean reconnect, String serverURI) {
Timber.d("Connect Complete. Reconnected: %s, serverUri:%s", reconnect, serverURI);
onConnect();
onConnect(wasConnectionLost);
wasConnectionLost = false;
}

@Override
Expand All @@ -163,6 +168,7 @@ public void connectionLost(Throwable cause) {
changeState(EndpointState.DISCONNECTED.withError(cause));
Timber.d("Releasing connectinglock");
connectingLock.release();
wasConnectionLost = true;
scheduler.scheduleMqttReconnect();
}

Expand Down Expand Up @@ -405,7 +411,7 @@ private void setWill(MqttConnectOptions m) {
}
}

private void onConnect() {
private void onConnect(boolean wasConnectionLost) {
Timber.d("MQTT connected!. Running onconnect handler (threadID %s)", Thread.currentThread());
scheduler.scheduleMqttMaybeReconnectAndPing(preferences.getKeepalive());

Expand Down Expand Up @@ -439,6 +445,10 @@ private void onConnect() {
subscribe(topics.toArray(new String[0]));

messageProcessor.resetMessageSleepBlock();

if (preferences.getPublishLocationOnConnect()) {
locationProcessor.publishLocationMessage(null); // TODO fix the trigger here
}
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
import dagger.hilt.android.qualifiers.ApplicationContext
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
import org.eclipse.paho.client.mqttv3.MqttConnectOptions
import org.greenrobot.eventbus.EventBus
import org.owntracks.android.BuildConfig
Expand All @@ -23,14 +31,6 @@ import org.owntracks.android.support.preferences.PreferencesStore
import org.owntracks.android.ui.AppShortcuts
import org.owntracks.android.ui.map.MapLayerStyle
import timber.log.Timber
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
@SuppressLint("NonConstantResourceId")
Expand Down Expand Up @@ -91,11 +91,15 @@ class Preferences @Inject constructor(
// SharedPreferencesImpl stores its listeners as a list of WeakReferences. So we shouldn't use a
// lambda as a listener, as that'll just get GC'd and then mysteriously disappear
// https://stackoverflow.com/a/3104265/352740
fun registerOnPreferenceChangedListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
fun registerOnPreferenceChangedListener(
listener: SharedPreferences.OnSharedPreferenceChangeListener
) {
preferencesStore.registerOnSharedPreferenceChangeListener(listener)
}

fun unregisterOnPreferenceChangedListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
fun unregisterOnPreferenceChangedListener(
listener: SharedPreferences.OnSharedPreferenceChangeListener
) {
preferencesStore.unregisterOnSharedPreferenceChangeListener(listener)
}

Expand Down Expand Up @@ -203,7 +207,9 @@ class Preferences @Inject constructor(
) {
importMethod.invoke(
this,
MonitoringMode.getByValue(messageConfiguration[configurationKey] as Int)
MonitoringMode.getByValue(
messageConfiguration[configurationKey] as Int
)
)
} else {
importMethod.invoke(this, messageConfiguration[configurationKey])
Expand All @@ -213,7 +219,7 @@ class Preferences @Inject constructor(
Timber.e(
"Tried to import $configurationKey but value is wrong type. Expected: ${
methods.getValue(configurationKey).parameterTypes.first().canonicalName
}, given ${messageConfiguration[configurationKey]?.javaClass?.canonicalName}",
}, given ${messageConfiguration[configurationKey]?.javaClass?.canonicalName}"
)
}
}
Expand Down Expand Up @@ -918,8 +924,12 @@ class Preferences @Inject constructor(
setInt(R.string.preferenceKeyTheme, actualValue)
when (actualValue) {
NIGHT_MODE_AUTO -> AppCompatDelegate.setDefaultNightMode(SYSTEM_NIGHT_AUTO_MODE)
NIGHT_MODE_ENABLE -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
NIGHT_MODE_DISABLE -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
NIGHT_MODE_ENABLE -> AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES
)
NIGHT_MODE_DISABLE -> AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_NO
)
}
}

Expand Down Expand Up @@ -989,21 +999,27 @@ class Preferences @Inject constructor(
)
@set:Import(keyResId = R.string.preferenceKeyEnableMapRotation)
var enableMapRotation: Boolean
get() = getBooleanOrDefault(R.string.preferenceKeyEnableMapRotation, R.bool.valEnableMapRotation)
get() = getBooleanOrDefault(
R.string.preferenceKeyEnableMapRotation,
R.bool.valEnableMapRotation
)
set(newValue) {
setBoolean(R.string.preferenceKeyEnableMapRotation, newValue)
}

@get:Export(
keyResId = R.string.preferenceKeyRepublishOnReconnect,
keyResId = R.string.preferenceKeyPublishLocationOnConnect,
exportModeMqtt = true,
exportModeHttp = false
)
@set:Import(keyResId = R.string.preferenceKeyRepublishOnReconnect)
var republishOnReconnect: Boolean
get() = getBooleanOrDefault(R.string.preferenceKeyRepublishOnReconnect, R.bool.valRepublishOnRecconect)
@set:Import(keyResId = R.string.preferenceKeyPublishLocationOnConnect)
var publishLocationOnConnect: Boolean
get() = getBooleanOrDefault(
R.string.preferenceKeyPublishLocationOnConnect,
R.bool.valPublishLocationOnConnect
)
set(newValue) {
setBoolean(R.string.preferenceKeyRepublishOnReconnect, newValue)
setBoolean(R.string.preferenceKeyPublishLocationOnConnect, newValue)
}

// Not used on public, as many people might use the same device type
Expand Down
2 changes: 1 addition & 1 deletion project/app/src/main/res/values/defaults.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<bool name="valRemoteConfiguration">false</bool>
<bool name="valShowRegionsOnMap">false</bool>
<bool name="valEnableMapRotation">true</bool>
<bool name="valRepublishOnRecconect">false</bool>
<bool name="valPublishLocationOnConnect">false</bool>
<bool name="valPegLocatorFastestIntervalToInterval">false</bool>

<string name="valEmpty" translatable="false" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<string name="preferenceKeyPubTopicBase">pubTopicBase</string>
<string name="preferenceKeyRemoteCommand">cmd</string>
<string name="preferenceKeyRemoteConfiguration">remoteConfiguration</string>
<string name="preferenceKeyRepublishOnReconnect">republishOnReconnect</string>
<string name="preferenceKeyPublishLocationOnConnect">publishOnConnect</string>
<string name="preferenceKeySetupNotCompleted">setupNotCompleted</string>
<string name="preferenceKeySub">sub</string>
<string name="preferenceKeySubQos">subQos</string>
Expand Down
4 changes: 2 additions & 2 deletions project/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ To allow this, please enable Location in the device settings."</string>
<string name="preferencesRemoteConfigurationSummary">"Enable configuration to be updated remotely (requires remote commands)"</string>
<string name="preferencesReporting">"Reporting"</string>
<string name="preferencesRepository">"Source Code"</string>
<string name="preferencesRepublishOnRecconect">"Republish on MQTT reconnect"</string>
<string name="preferencesRepublishOnRecconectSummary">"Publish the last known location and current extended data on re-connecting to MQTT"</string>
<string name="preferencesRepublishOnRecconect">"Publish location on MQTT connect"</string>
<string name="preferencesRepublishOnRecconectSummary">"Publish the last known location and current extended data immediately on connecting to MQTT"</string>
<string name="preferencesReverseGeocodeProvider">"Reverse Geocode Provider"</string>
<string name="preferencesSecurity">"Security"</string>
<string name="preferencesServer">"Connection"</string>
Expand Down
4 changes: 2 additions & 2 deletions project/app/src/main/res/xml/preferences_reporting.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
app:summary="@string/preferencesPubExtendedDataSummary"
app:title="@string/preferencesPubExtendedData" />
<androidx.preference.SwitchPreferenceCompat
app:defaultValue="@bool/valRepublishOnRecconect"
app:defaultValue="@bool/valPublishLocationOnConnect"
app:iconSpaceReserved="false"
app:key="@string/preferenceKeyRepublishOnReconnect"
app:key="@string/preferenceKeyPublishLocationOnConnect"
app:summary="@string/preferencesRepublishOnRecconectSummary"
app:title="@string/preferencesRepublishOnRecconect" />
</PreferenceScreen>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class MessageProcessorEndpointMqttTest {
@Test
fun `MQTT Endpoint generates correct topics to subscribe to from single default subTopic`() {
val endpoint =
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext)
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext, null)
val subTopic = "owntracks/+/+"
val topics =
endpoint.getTopicsToSubscribeTo(subTopic, true, "/info", "/events", "/waypoints")
Expand All @@ -33,7 +33,7 @@ class MessageProcessorEndpointMqttTest {
@Test
fun `MQTT Endpoint generates correct topics to subscribe to from single custom subTopic`() {
val endpoint =
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext)
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext, null)
val subTopic = "othertopic/+/+"
val topics =
endpoint.getTopicsToSubscribeTo(subTopic, true, "/info", "/events", "/waypoints")
Expand All @@ -45,7 +45,7 @@ class MessageProcessorEndpointMqttTest {
@Test
fun `MQTT Endpoint generates correct topics to subscribe to from multiple subTopics`() {
val endpoint =
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext)
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext, null)
val subTopic = "owntracks/+/+ othertopic/+"
val topics =
endpoint.getTopicsToSubscribeTo(subTopic, true, "/info", "/events", "/waypoints")
Expand All @@ -61,7 +61,7 @@ class MessageProcessorEndpointMqttTest {
@Test
fun `MQTT Endpoint generates correct topics to subscribe to from multiple subTopics with info not requested`() {
val endpoint =
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext)
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext, null)
val subTopic = "owntracks/+/+ othertopic/+"
val topics =
endpoint.getTopicsToSubscribeTo(subTopic, false, "/info", "/events", "/waypoints")
Expand All @@ -77,7 +77,7 @@ class MessageProcessorEndpointMqttTest {
@Test
fun `MQTT Endpoint generates correct topics to subscribe to from wildcard topic`() {
val endpoint =
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext)
MessageProcessorEndpointMqtt(null, null, null, null, null, null, applicationContext, null)
val subTopic = "owntracks/#"
val topics =
endpoint.getTopicsToSubscribeTo(subTopic, true, "/info", "/events", "/waypoints")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class ParserTest {
val regions: MutableList<String> = LinkedList()
regions.add("Testregion1")
regions.add("Testregion2")
messageLocation = MessageLocation(MessageCreatedAtNow(FakeClock())).apply {
messageLocation = MessageLocation(MessageCreatedAtNow(FakeFixedClock())).apply {
accuracy = 10
altitude = 20
latitude = 50.1
Expand Down Expand Up @@ -727,7 +727,7 @@ class ParserTest {
}
//endregion

inner class FakeClock : Clock {
inner class FakeFixedClock : Clock {
override val time: Long = 25
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ class PreferencesGettersAndSetters(
on { getString(eq(R.string.preferenceKeyPubTopicBase)) } doReturn "pubTopicBase"
on { getString(eq(R.string.preferenceKeyRemoteCommand)) } doReturn "cmd"
on { getString(eq(R.string.preferenceKeyRemoteConfiguration)) } doReturn "remoteConfiguration"
on { getString(eq(R.string.preferenceKeyRepublishOnReconnect)) } doReturn "republishOnReconnect"
on { getString(eq(R.string.preferenceKeyPublishLocationOnConnect)) } doReturn "republishOnReconnect"
on { getString(eq(R.string.preferenceKeyReverseGeocodeProvider)) } doReturn "reverseGeocodeProvider"
on { getString(eq(R.string.preferenceKeySetupNotCompleted)) } doReturn "setupNotCompleted"
on { getString(eq(R.string.preferenceKeySub)) } doReturn "sub"
Expand Down
1 change: 1 addition & 0 deletions util/mqtt-local/mosquitto.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
allow_anonymous false
log_type all
password_file /mosquitto/config/mosquitto.password

listener 1883
Expand Down

0 comments on commit 8bf4426

Please sign in to comment.