kopia lustrzana https://github.com/ge0rg/aprsdroid
131 wiersze
3.7 KiB
Scala
131 wiersze
3.7 KiB
Scala
package org.aprsdroid.app
|
|
|
|
import _root_.android.location.Location
|
|
import _root_.net.ab0oo.aprs.parser._
|
|
|
|
import scala.math.abs
|
|
|
|
object AprsPacket {
|
|
val QRG_RE = ".*?(\\d{2,3}[.,]\\d{3,4}).*?".r
|
|
|
|
def passcode(callssid : String) : Int = {
|
|
// remove ssid, uppercase, add \0 for odd-length calls
|
|
val call = callssid.split("-")(0).toUpperCase() + "\u0000"
|
|
var hash = 0x73e2
|
|
for (i <- 0 to call.length-2 by 2) {
|
|
hash ^= call(i) << 8
|
|
hash ^= call(i+1)
|
|
}
|
|
hash & 0x7fff
|
|
}
|
|
def passcodeAllowed(callssid : String, pass : String, optional : Boolean) = {
|
|
pass match {
|
|
case "" => optional
|
|
case "-1" => optional
|
|
case _ => (passcode(callssid).toString() == pass)
|
|
}
|
|
}
|
|
|
|
|
|
def formatCallSsid(callsign : String, ssid : String) : String = {
|
|
if (ssid != null && ssid != "")
|
|
return callsign + "-" + ssid
|
|
else
|
|
return callsign
|
|
}
|
|
|
|
def m2ft(meter : Double) : Int = (meter*3.2808399).asInstanceOf[Int]
|
|
|
|
def mps2kt(mps : Double) : Int = (mps*1.94384449).asInstanceOf[Int]
|
|
|
|
def formatAltitude(location : Location) : String = {
|
|
if (location.hasAltitude)
|
|
"/A=%06d".formatLocal(null, m2ft(location.getAltitude))
|
|
else
|
|
""
|
|
}
|
|
|
|
def formatCourseSpeed(location : Location) : String = {
|
|
// only report speeds above 2m/s (7.2km/h)
|
|
if (location.hasSpeed && location.hasBearing)
|
|
// && location.getSpeed > 2)
|
|
"%03d/%03d".formatLocal(null, location.getBearing.asInstanceOf[Int],
|
|
mps2kt(location.getSpeed))
|
|
else
|
|
""
|
|
}
|
|
|
|
def formatFreq(csespd : String, freq : Float) : String = {
|
|
if (freq == 0) "" else {
|
|
val prefix = if (csespd.length() > 0) "/" else ""
|
|
prefix + "%07.3fMHz".formatLocal(null, freq)
|
|
}
|
|
}
|
|
|
|
def formatLogin(callsign : String, ssid : String, passcode : String, version : String) : String = {
|
|
"user %s pass %s vers %s".format(formatCallSsid(callsign, ssid), passcode, version)
|
|
}
|
|
|
|
def formatRangeFilter(loc : Location, range : Int) : String = {
|
|
if (loc != null)
|
|
"r/%1.3f/%1.3f/%d".formatLocal(null, loc.getLatitude, loc.getLongitude, range)
|
|
else
|
|
""
|
|
}
|
|
|
|
val DirectionsLatitude = "NS";
|
|
val DirectionsLongitude = "EW";
|
|
def formatDMS(coordinate : Float, nesw : String) = {
|
|
val dms = Location.convert(abs(coordinate), Location.FORMAT_SECONDS).split(":")
|
|
val nesw_idx = (coordinate < 0).compare(false)
|
|
"%2s° %2s' %s\" %s".format(dms(0), dms(1), dms(2), nesw(nesw_idx))
|
|
}
|
|
|
|
def formatCoordinates(latitude : Float, longitude : Float) = {
|
|
(AprsPacket.formatDMS(latitude, DirectionsLatitude),
|
|
AprsPacket.formatDMS(longitude, DirectionsLongitude))
|
|
}
|
|
|
|
def parseQrg(comment : String) : String = {
|
|
comment match {
|
|
case QRG_RE(qrg) => qrg
|
|
case _ => null
|
|
}
|
|
}
|
|
|
|
def parseHostPort(hostport : String, defaultport : Int) : (String, Int) = {
|
|
val splits = hostport.trim().split(":")
|
|
try {
|
|
// assume string:int
|
|
return (splits(0), splits(1).toInt)
|
|
} catch {
|
|
// fallback to default port if none/bad one given
|
|
case _ : Throwable => return (splits(0), defaultport)
|
|
}
|
|
}
|
|
|
|
// position ambiguity re-defined as 67% (Android's Location)
|
|
// of the worst-case error from the ambiguity field
|
|
//
|
|
// Best possible APRS precision at the equator is ~18m, we assume
|
|
// proper rounding (so max. 9m between actual and reported position)
|
|
// and take 67% of that.
|
|
val APRS_AMBIGUITY_METERS = Array(6, 37185, 6200, 620, 62)
|
|
|
|
def position2location(ts : Long, p : Position, cse : CourseAndSpeedExtension = null) = {
|
|
val l = new Location("APRS")
|
|
l.setLatitude(p.getLatitude())
|
|
l.setLongitude(p.getLongitude())
|
|
l.setTime(ts)
|
|
l.setAccuracy(APRS_AMBIGUITY_METERS(p.getPositionAmbiguity()))
|
|
if (cse != null) {
|
|
// course == bearing?
|
|
l.setBearing(cse.getCourse)
|
|
// APRS uses knots, Location expects m/s
|
|
l.setSpeed(cse.getSpeed / 1.94384449f)
|
|
}
|
|
// todo: bearing, speed
|
|
l
|
|
}
|
|
}
|