aprsdroid/src/backend/AprsBackend.scala

177 wiersze
5.1 KiB
Scala

package org.aprsdroid.app
import android.Manifest
import android.os.Build
import _root_.net.ab0oo.aprs.parser.APRSPacket
import _root_.java.io.{InputStream, OutputStream}
object AprsBackend {
/** "Modular" system to connect to an APRS backend.
* The backend config consists of three items backed by prefs values:
* - *proto* inside the connection ("aprsis", "afsk", "kiss", "tnc2", "kenwood") - ProtoInfo class
* - *link* type ("bluetooth", "usb", "tcpip"; only for "kiss", "tnc2", "kenwood") - BackendInfo class
* - *aprsis* mode ("tcp", "http", "udp"; only for proto=aprsis) - BackendInfo class
*/
val DEFAULT_CONNTYPE = "tcp"
val DEFAULT_LINK = "tcpip"
val DEFAULT_PROTO = "aprsis"
val PASSCODE_NONE = 0
val PASSCODE_OPTIONAL = 1
val PASSCODE_REQUIRED = 2
val CAN_RECEIVE = 1
val CAN_XMIT = 2
val CAN_DUPLEX = 3
// "struct" for APRS backend information
class BackendInfo(
val create : (AprsService, PrefsWrapper) => AprsBackend,
val prefxml : Int,
val permissions : Set[String],
val duplex : Int,
val need_passcode : Int
) {}
val BLUETOOTH_PERMISSION = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Manifest.permission.BLUETOOTH_CONNECT
} else {
Manifest.permission.BLUETOOTH_ADMIN
}
// map from old "backend" to new proto-link-aprsis (defaults are bluetooth and tcp)
val backend_upgrade = Map(
"tcp" -> "aprsis-tcpip-tcp",
"udp" -> "aprsis-tcpip-udp",
"http" -> "aprsis-tcpip-http",
"afsk" -> "afsk-bluetooth-tcp",
"bluetooth" -> "kiss-bluetooth-tcp",
"kenwood" -> "kenwood-bluetooth-tcp",
"tcptnc" -> "kiss-tcpip-tcp",
"usb" -> "kiss-usb-tcp"
)
// add your own BackendInfo here
val backend_collection = Map(
"udp" -> new BackendInfo(
(s, p) => new UdpUploader(p),
R.xml.backend_udp,
Set(),
CAN_XMIT,
PASSCODE_REQUIRED),
"http" -> new BackendInfo(
(s, p) => new HttpPostUploader(p),
R.xml.backend_http,
Set(),
CAN_XMIT,
PASSCODE_REQUIRED),
"afsk" -> new BackendInfo(
(s, p) => new AfskUploader(s, p),
0,
Set(Manifest.permission.RECORD_AUDIO),
CAN_DUPLEX,
PASSCODE_NONE),
"tcp" -> new BackendInfo(
(s, p) => new TcpUploader(s, p),
R.xml.backend_tcp,
Set(),
CAN_DUPLEX,
PASSCODE_OPTIONAL),
"bluetooth" -> new BackendInfo(
(s, p) => new BluetoothTnc(s, p),
R.xml.backend_bluetooth,
Set(BLUETOOTH_PERMISSION),
CAN_DUPLEX,
PASSCODE_NONE),
"tcpip" -> new BackendInfo(
(s, p) => new TcpUploader(s, p),
R.xml.backend_tcptnc,
Set(),
CAN_DUPLEX,
PASSCODE_NONE),
"usb" -> new BackendInfo(
(s, p) => new UsbTnc(s, p),
R.xml.backend_usb,
Set(),
CAN_DUPLEX,
PASSCODE_NONE)
)
class ProtoInfo(
val create : (AprsService, InputStream, OutputStream) => TncProto,
val prefxml : Int,
val link : String
) {}
val proto_collection = Map(
"aprsis" -> new ProtoInfo(
(s, is, os) => new AprsIsProto(s, is, os),
R.xml.proto_aprsis, "aprsis"),
"afsk" -> new ProtoInfo(
null,
R.xml.proto_afsk, null),
"kiss" -> new ProtoInfo(
(s, is, os) => new KissProto(s, is, os),
R.xml.proto_kiss, "link"),
"tnc2" -> new ProtoInfo(
(s, is, os) => new Tnc2Proto(is, os),
R.xml.proto_tnc2, "link"),
"kenwood" -> new ProtoInfo(
(s, is, os) => new KenwoodProto(s, is, os),
R.xml.proto_kenwood, "link")
);
def defaultProtoInfo(p : String) : ProtoInfo = {
proto_collection.get(p) match {
case Some(pi) => pi
case None => proto_collection("aprsis")
}
}
def defaultProtoInfo(prefs : PrefsWrapper) : ProtoInfo = defaultProtoInfo(prefs.getProto())
def defaultBackendInfo(prefs : PrefsWrapper) : BackendInfo = {
val pi = defaultProtoInfo(prefs)
val link = if (pi.link != null) { prefs.getString(pi.link, DEFAULT_LINK) } else { prefs.getProto() }
backend_collection.get(link) match {
case Some(bi) => bi
case None => backend_collection(DEFAULT_CONNTYPE)
}
}
def defaultBackendPermissions(prefs : PrefsWrapper) : Set[String] = {
val perms = scala.collection.mutable.Set[String]()
perms ++= AprsBackend.defaultBackendInfo(prefs).permissions
if (prefs.getProto() == "kenwood" && prefs.getBoolean("kenwood.gps", false))
perms += (Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
perms += (Manifest.permission.POST_NOTIFICATIONS)
}
perms.toSet
}
def instanciateUploader(service : AprsService, prefs : PrefsWrapper) : AprsBackend = {
defaultBackendInfo(prefs).create(service, prefs)
}
def instanciateProto(service : AprsService, is : InputStream, os : OutputStream) : TncProto = {
defaultProtoInfo(service.prefs).create(service, is, os)
}
def prefxml_proto(prefs : PrefsWrapper) = {
defaultProtoInfo(prefs).prefxml
}
def prefxml_backend(prefs : PrefsWrapper) = {
defaultBackendInfo(prefs).prefxml
}
}
abstract class AprsBackend(prefs : PrefsWrapper) {
val login = prefs.getLoginString()
// returns true if successfully started.
// when returning false, AprsService.postPosterStarted() must be called
def start() : Boolean
def update(packet : APRSPacket) : String
def stop()
}