diff --git a/app/build.gradle b/app/build.gradle
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -95,7 +95,7 @@
implementation 'com.google.protobuf:protobuf-java:3.17.2'
// mqtt library
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
- implementation 'com.github.hannesa2:paho.mqtt.android:3.5.3'
+ implementation 'com.github.hannesa2:paho.mqtt.android:4.1'
// ViewModel
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,6 +9,7 @@
+
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/gtfs/GtfsRtPositionsRequest.kt b/app/src/main/java/it/reyboz/bustorino/backend/gtfs/GtfsRtPositionsRequest.kt
--- a/app/src/main/java/it/reyboz/bustorino/backend/gtfs/GtfsRtPositionsRequest.kt
+++ b/app/src/main/java/it/reyboz/bustorino/backend/gtfs/GtfsRtPositionsRequest.kt
@@ -28,6 +28,7 @@
errorListener: Response.ErrorListener?,
val listener: RequestListener) :
Request>(Method.GET, URL_POSITION, errorListener) {
+
override fun parseNetworkResponse(response: NetworkResponse?): Response> {
if (response == null){
return Response.error(VolleyError("Null response"))
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/mato/MQTTMatoClient.kt b/app/src/main/java/it/reyboz/bustorino/backend/mato/MQTTMatoClient.kt
--- a/app/src/main/java/it/reyboz/bustorino/backend/mato/MQTTMatoClient.kt
+++ b/app/src/main/java/it/reyboz/bustorino/backend/mato/MQTTMatoClient.kt
@@ -5,13 +5,10 @@
import androidx.lifecycle.LifecycleOwner
import info.mqtt.android.service.Ack
import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
import org.eclipse.paho.client.mqttv3.*
import info.mqtt.android.service.MqttAndroidClient
import info.mqtt.android.service.QoS
-import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
import org.json.JSONArray
import org.json.JSONException
import java.lang.ref.WeakReference
@@ -34,10 +31,11 @@
private lateinit var lifecycle: LifecycleOwner
private var context: Context?= null
+ private var connectionTrials = 0
private fun connect(context: Context, iMqttActionListener: IMqttActionListener?){
- val clientID = "mqttjs_${getRandomString(8)}"
+ val clientID = "mqtt-explorer-${getRandomString(8)}"//"mqttjs_${getRandomString(8)}"
client = MqttAndroidClient(context,SERVER_ADDR,clientID,Ack.AUTO_ACK)
@@ -49,6 +47,7 @@
headersPars.setProperty("Host","mapi.5t.torino.it")
options.customWebSocketHeaders = headersPars
+ Log.d(DEBUG_TAG,"client name: $clientID")
//actually connect
client.connect(options,null, iMqttActionListener)
isStarted = true
@@ -63,28 +62,47 @@
Log.d(DEBUG_TAG, "Connected to server, reconnect: $reconnect")
Log.d(DEBUG_TAG, "Have listeners: $respondersMap")
}
+ private fun connectTopic(topic: String){
+ if(context==null){
+ Log.e(DEBUG_TAG, "Trying to connect but context is null")
+ return
+ }
+ connectionTrials += 1
+ connect(context!!, object : IMqttActionListener{
+ override fun onSuccess(asyncActionToken: IMqttToken?) {
+ val disconnectedBufferOptions = DisconnectedBufferOptions()
+ disconnectedBufferOptions.isBufferEnabled = true
+ disconnectedBufferOptions.bufferSize = 100
+ disconnectedBufferOptions.isPersistBuffer = false
+ disconnectedBufferOptions.isDeleteOldestMessages = false
+ client.setBufferOpts(disconnectedBufferOptions)
+ client.subscribe(topic, QoS.AtMostOnce.value)
+ isStarted = true
+ }
+
+ override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
+ Log.e(DEBUG_TAG, "FAILED To connect to the server",exception)
+ if (connectionTrials < 10) {
+ Log.d(DEBUG_TAG, "Reconnecting")
+ connectTopic(topic)
+ }
+ else {
+ //reset connection trials
+ connectionTrials = 0
+ }
+ }
+
+ })
+ }
fun startAndSubscribe(lineId: String, responder: MQTTMatoListener, context: Context): Boolean{
//start the client, and then subscribe to the topic
val topic = mapTopic(lineId)
+ this.context = context.applicationContext
synchronized(this) {
if(!isStarted){
- connect(context, object : IMqttActionListener{
- override fun onSuccess(asyncActionToken: IMqttToken?) {
- val disconnectedBufferOptions = DisconnectedBufferOptions()
- disconnectedBufferOptions.isBufferEnabled = true
- disconnectedBufferOptions.bufferSize = 100
- disconnectedBufferOptions.isPersistBuffer = false
- disconnectedBufferOptions.isDeleteOldestMessages = false
- client.setBufferOpts(disconnectedBufferOptions)
- client.subscribe(topic, QoS.AtMostOnce.value)
- }
- override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
- Log.e(DEBUG_TAG, "FAILED To connect to the server")
- }
-
- })
+ connectTopic(topic)
//wait for connection
} else {
client.subscribe(topic, QoS.AtMostOnce.value)
@@ -137,16 +155,22 @@
return currentPositions
}
- fun sendUpdateToResponders(responders: ArrayList>): Boolean{
- var sent = false
- for (wrD in responders)
- if (wrD.get() == null)
+ private fun sendUpdateToResponders(responders: ArrayList>): Int{
+ //var sent = false
+ var count = 0
+ for (wrD in responders) {
+ if (wrD.get() == null) {
+ Log.d(DEBUG_TAG, "Removing weak reference")
responders.remove(wrD)
+ }
else {
wrD.get()!!.onUpdateReceived(currentPositions)
- sent = true
+ //sent = true
+ count++
}
- return sent
+ }
+
+ return count
}
override fun connectionLost(cause: Throwable?) {
@@ -185,7 +209,7 @@
override fun messageArrived(topic: String?, message: MqttMessage?) {
if (topic==null || message==null) return
-
+ //Log.d(DEBUG_TAG,"Arrived message on topic $topic, ${String(message.payload)}")
parseMessageAndAddToList(topic, message)
//GlobalScope.launch { }
@@ -243,17 +267,20 @@
it[vehicleId] = posUpdate
valid = true
}
- var sent = false
+ //sending
+ //Log.d(DEBUG_TAG, "Parsed update on topic $topic, line $lineId, responders $respondersMap")
+ var cc = 0
if (LINES_ALL in respondersMap.keys) {
- sent = sendUpdateToResponders(respondersMap[LINES_ALL]!!)
-
-
+ val count = sendUpdateToResponders(respondersMap[LINES_ALL]!!)
+ cc +=count
}
+
if(lineId in respondersMap.keys){
- sent = sendUpdateToResponders(respondersMap[lineId]!!) or sent
+ cc += sendUpdateToResponders(respondersMap[lineId]!!)
}
- if(!sent){
+ //Log.d(DEBUG_TAG, "Sent to $cc responders, have $respondersMap")
+ if(cc==0){
Log.w(DEBUG_TAG, "We have received an update but apparently there is no one to send it")
var emptyResp = true
for(en in respondersMap.values){
@@ -270,8 +297,10 @@
}
//Log.d(DEBUG_TAG, "We have update on line $lineId, vehicle $vehicleId")
} catch (e: JSONException){
- Log.e(DEBUG_TAG,"Cannot decipher message on topic $topic, line $lineId, veh $vehicleId")
- e.printStackTrace()
+ Log.w(DEBUG_TAG,"Cannot decipher message on topic $topic, line $lineId, veh $vehicleId (bad JSON)")
+
+ } catch (e: Exception){
+ Log.e(DEBUG_TAG, "Exception occurred", e)
}
}
diff --git a/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt b/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt
@@ -57,9 +57,9 @@
for(trip in tripsList){
queriedMatoTrips.add(trip)
matoRepository.requestTripUpdate(trip,{error->
- Log.e(DEBUG_TAG, "Cannot download Gtfs Trip $trip")
- val stacktrace = error.stackTrace.take(5)
- Log.w(DEBUG_TAG, "Stacktrace:\n$stacktrace")
+ Log.e(DEBUG_TAG, "Cannot download Gtfs Trip $trip", error)
+ //val stacktrace = error.stackTrace.take(5)
+ //Log.w(DEBUG_TAG, "Stacktrace:\n$stacktrace")
failedMatoTripsDownload.add(trip)
requestCountDown.countDown()
}){
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
@@ -540,7 +540,8 @@
val paint = Paint()
paint.color = ContextCompat.getColor(requireContext(),R.color.line_drawn_poly)
paint.isAntiAlias = true
- paint.strokeWidth = 16f
+ paint.strokeWidth = 13f
+
paint.style = Paint.Style.FILL_AND_STROKE
paint.strokeJoin = Paint.Join.ROUND
paint.strokeCap = Paint.Cap.ROUND
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt
--- a/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt
@@ -20,6 +20,7 @@
import android.app.Application
import android.util.Log
import androidx.lifecycle.*
+import com.android.volley.DefaultRetryPolicy
import com.android.volley.Response
import it.reyboz.bustorino.backend.NetworkVolleyManager
import it.reyboz.bustorino.backend.gtfs.GtfsRtPositionsRequest
@@ -70,7 +71,7 @@
}
val time = System.currentTimeMillis()
if(lastTimeReceived == (0.toLong()) || (time-lastTimeReceived)>500){
- updatesLiveData.value = (mupds)
+ updatesLiveData.postValue(mupds)
lastTimeReceived = time
}
@@ -167,8 +168,6 @@
}
}
//Gtfs Real time
-
-
private val gtfsPositionsReqListener = object: GtfsRtPositionsRequest.Companion.RequestListener{
override fun onResponse(response: ArrayList?) {
Log.i(DEBUG_TI,"Got response from the GTFS RT server")
@@ -189,13 +188,16 @@
}
private val positionRequestErrorListener = Response.ErrorListener {
- Log.e(DEBUG_TI, "Could not download the update, error:\n"+it.stackTrace)
+ Log.e(DEBUG_TI, "Could not download the update", it)
gtfsRtRequestRunning.postValue(false)
}
fun requestGTFSUpdates(){
if(gtfsRtRequestRunning.value == null || !gtfsRtRequestRunning.value!!) {
val request = GtfsRtPositionsRequest(positionRequestErrorListener, gtfsPositionsReqListener)
+ request.setRetryPolicy(
+ DefaultRetryPolicy(1000,10,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)
+ )
netVolleyManager.requestQueue.add(request)
Log.i(DEBUG_TI, "Requested GTFS realtime position updates")
gtfsRtRequestRunning.value = true
@@ -211,6 +213,6 @@
}
companion object{
- private const val DEBUG_TI = "BusTO-MQTTLiveData"
+ private const val DEBUG_TI = "BusTO-LivePosViewModel"
}
}
\ No newline at end of file
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -168,9 +168,10 @@
- Canale unico delle notifiche
- Database
+ Canale default delle notifiche
+ Operazioni sul database
Informazioni sul database (aggiornamento)
+
Downloading trips from MaTO server
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -196,8 +196,9 @@
-->
Default
Default channel for notifications
- Database
- Notifications on the update of the database
+ Database operations
+ Updates of the app database
+
Downloading trips from MaTO server
Asked for %1$s permission too many times