From d0a3c881af4293c99ced3e8a6db79071700737ba Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 21 Dec 2024 16:45:44 -0800 Subject: [PATCH] Igate Updates --- res/values/strings.xml | 6 +++++ res/xml/igate.xml | 12 ++++++++++ res/xml/preferences.xml | 16 +++++++++++++ src/AprsService.scala | 2 +- src/DigipeaterService.scala | 4 ++-- src/IgatePrefs.scala | 46 +++++++++++++++++++++++++++++++++++++ src/IgateService.scala | 40 ++++++++++++++++++++++++++++---- src/PrefsWrapper.scala | 3 +++ 8 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 res/xml/igate.xml create mode 100644 src/IgatePrefs.scala diff --git a/res/values/strings.xml b/res/values/strings.xml index 6bc1f4e..1501b15 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -116,6 +116,11 @@ Enable Digipeater Digi & Regen Functions +IGating Preferences +IGate +Enable IGate +IGate Settings + OSM Maps Enable offline mapping Uses locally hosted tile server @@ -214,6 +219,7 @@ Enter your beacon comment APRS Connection Digipeating Preferences +IGating Prefences Messaging Preferences Connection Protocol diff --git a/res/xml/igate.xml b/res/xml/igate.xml new file mode 100644 index 0000000..3a833b6 --- /dev/null +++ b/res/xml/igate.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index 4285a1e..a379c00 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -90,6 +90,22 @@ + + + + + + + + + + diff --git a/src/AprsService.scala b/src/AprsService.scala index 1c798d9..2d911f1 100644 --- a/src/AprsService.scala +++ b/src/AprsService.scala @@ -530,7 +530,7 @@ class AprsService extends Service { // Process the incoming post digipeaterService.processIncomingPost(post) - igateService.handlePostSubmitData(post) + igateService.checkAprsisService(post) } diff --git a/src/DigipeaterService.scala b/src/DigipeaterService.scala index 3e9deca..f77ccc6 100644 --- a/src/DigipeaterService.scala +++ b/src/DigipeaterService.scala @@ -5,7 +5,7 @@ import _root_.net.ab0oo.aprs.parser._ import java.util.Date class DigipeaterService(prefs: PrefsWrapper, TAG: String, sendDigipeatedPacket: String => Unit) { - private val recentDigipeats: mutable.Map[String, Instant] = mutable.Map() + private val recentDigipeats: mutable.Map[String, Date] = mutable.Map() def dedupeTime: Int = prefs.getStringInt("p.dedupe", 30) // Fetch the latest dedupe time from preferences def digipeaterpath: String = prefs.getString("digipeater_path", "WIDE1,WIDE2") // Fetch digipeater path from preferences @@ -14,7 +14,7 @@ class DigipeaterService(prefs: PrefsWrapper, TAG: String, sendDigipeatedPacket: def storeDigipeat(sourceCall: String, destinationCall: String, payload: String): Unit = { // Unique identifier using source call, destination call, and payload val key = s"$sourceCall>$destinationCall:$payload" - recentDigipeats(key) = new.Date() // Store the current timestamp + recentDigipeats(key) = new Date() // Store the current timestamp } // Function to filter digipeats that are older than dedupeTime seconds diff --git a/src/IgatePrefs.scala b/src/IgatePrefs.scala new file mode 100644 index 0000000..ebb94b3 --- /dev/null +++ b/src/IgatePrefs.scala @@ -0,0 +1,46 @@ +package org.aprsdroid.app + +import _root_.android.content.SharedPreferences +import _root_.android.os.Bundle +import _root_.android.preference.{PreferenceActivity, CheckBoxPreference} + +class IgatePrefs extends PreferenceActivity with SharedPreferences.OnSharedPreferenceChangeListener { + + lazy val prefs = new PrefsWrapper(this) + + def loadXml() { + // Load only the p.igating preference + addPreferencesFromResource(R.xml.igate) // Ensure this XML only contains p.igating + } + + override def onCreate(savedInstanceState: Bundle) { + super.onCreate(savedInstanceState) + loadXml() + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this) + + // Update preferences state on activity creation + updateCheckBoxState() + } + + override def onDestroy() { + super.onDestroy() + getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this) + } + + override def onSharedPreferenceChanged(sp: SharedPreferences, key: String) { + key match { + case "p.igating" => + // Handle changes to "p.igating" preference (if necessary) + updateCheckBoxState() + case _ => // No action for other preferences + } + } + + // This method will enable/disable the checkboxes based on their current state + private def updateCheckBoxState(): Unit = { + val igatingPref = findPreference("p.igating").asInstanceOf[CheckBoxPreference] + + // Add logic if needed to handle the "p.igating" preference state + // For example, enabling or disabling other preferences based on this preference. + } +} diff --git a/src/IgateService.scala b/src/IgateService.scala index dfb0d19..74a7f79 100644 --- a/src/IgateService.scala +++ b/src/IgateService.scala @@ -8,7 +8,7 @@ import _root_.android.util.Log class IgateService(service : AprsService, prefs: PrefsWrapper) { val TAG = "IgateService" - val hostport = prefs.getString("tcp.server", "theconnectdesk.com") + val hostport = prefs.getString("tcp.server", "rotate.aprs2.net") val so_timeout = prefs.getStringInt("tcp.sotimeout", 30) var conn: TcpSocketThread = _ @@ -50,6 +50,8 @@ class IgateService(service : AprsService, prefs: PrefsWrapper) { def init_socket(): Unit = { val (host, port) = parseHostPort(hostport) Log.d(TAG, s"init_socket() - Connecting to $host on port $port") + service.addPost(StorageDatabase.Post.TYPE_DIGI, "APRS-IS", s"Connecting to $host:$port") + var attempts = 0 while (running) { @@ -65,6 +67,7 @@ class IgateService(service : AprsService, prefs: PrefsWrapper) { sendLogin() Log.d(TAG, "init_socket() - Connection established") + service.addPost(StorageDatabase.Post.TYPE_DIGI, "APRS-IS", "Connection Established") return // If connection is successful, exit the loop } catch { case e: java.net.UnknownHostException => @@ -98,16 +101,16 @@ class IgateService(service : AprsService, prefs: PrefsWrapper) { } } - // Send login information to the APRS-IS server def sendLogin(): Unit = { val callsign = prefs.getCallSsid() val passcode = prefs.getPasscode() // Retrieve passcode from preferences val version = "APRSdroid iGate" // Version information (as in Python example) + val filter = "" // Format the login message as per the Python example val loginMessage = s"user $callsign pass $passcode vers $version\r\n" - val filterMessage = s"#filter ${prefs.getString("tcp.filter", "")}\r\n" // Retrieve filter from preferences + val filterMessage = s"#filter $filter\r\n" // Retrieve filter from preferences Log.d(TAG, s"sendLogin() - Sending login: $loginMessage") Log.d(TAG, s"sendLogin() - Sending filter: $filterMessage") @@ -259,6 +262,12 @@ class IgateService(service : AprsService, prefs: PrefsWrapper) { val receivedData = bufferedReader.readLine() if (receivedData != null) { Log.d(TAG, s"run() - Received data from server: $receivedData") + + if (!receivedData.startsWith("#")) { + // If it does not start with "# aprsc", call addPost + service.addPost(StorageDatabase.Post.TYPE_DIGI, "APRS-IS Received", receivedData) + } + } else { Log.e(TAG, "run() - No data received, server might have closed the connection") running = false // Stop the thread if no data is received @@ -316,13 +325,28 @@ class IgateService(service : AprsService, prefs: PrefsWrapper) { } } + def checkAprsisService(data: String): Unit = { + // Check if the digipeating setting is enabled + if (!prefs.isIgateEnabled()) { + Log.d("APRSdroid.Service", "IGating is disabled") + return + } + handlePostSubmitData(data) + } + def modifyData(data: String): String = { + // Check if data contains "RFONLY" or "TCPIP" + if (data.contains("RFONLY") || data.contains("TCPIP")) { + Log.d(TAG, s"modifyData() - RFONLY or TCPIP found: $data") + return null // Return the data as is if it contains "RFONLY" or "TCPIP" + } + // Find the index of the first colon val colonIndex = data.indexOf(":") if (colonIndex != -1) { // Insert ",qAR" before the first colon - data.substring(0, colonIndex) + ",qAR" + data.substring(colonIndex) + data.substring(0, colonIndex) + ",qAR," + prefs.getCallSsid + data.substring(colonIndex) } else { // If there's no colon, return the data as is (or handle this case as needed) data @@ -336,12 +360,20 @@ class IgateService(service : AprsService, prefs: PrefsWrapper) { // Modify the data before sending it to the server val modifiedData = modifyData(data) + // If the modified data is null, skip further processing + if (modifiedData == null) { + Log.d(TAG, "handlePostSubmitData() - Skipping data processing due to RFONLY/TCPIP in packet") + return // Stop further processing if the packet contains RFONLY or TCPIP + } + // Log the modified data to confirm the change Log.d(TAG, s"handlePostSubmitData() - Modified data: $modifiedData") // Send the modified data to the APRS-IS server (or other logic as necessary) if (conn != null) { conn.sendData(modifiedData) // Send it to the server + service.addPost(StorageDatabase.Post.TYPE_DIGI, "APRS-IS Sent", modifiedData) + } else { Log.d(TAG, "handlePostSubmitData() - No active connection to send data.") } diff --git a/src/PrefsWrapper.scala b/src/PrefsWrapper.scala index 991eac8..f1939e6 100644 --- a/src/PrefsWrapper.scala +++ b/src/PrefsWrapper.scala @@ -12,6 +12,9 @@ class PrefsWrapper(val context : Context) { def getString(key : String, defValue : String) = prefs.getString(key, defValue) def getBoolean(key : String, defValue : Boolean) = prefs.getBoolean(key, defValue) + def isIgateEnabled(): Boolean = { + prefs.getBoolean("p.igating", false) + } def isDigipeaterEnabled(): Boolean = { prefs.getBoolean("p.digipeating", false) }