kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
reformat per coding conventions
rodzic
2c75d0dee7
commit
5b653d29f8
|
@ -63,8 +63,7 @@ data class DataPacket(
|
|||
parcel.readInt(),
|
||||
parcel.readParcelable(MessageStatus::class.java.classLoader),
|
||||
parcel.readInt()
|
||||
) {
|
||||
}
|
||||
)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
|
|
@ -363,7 +363,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
rater.monitor() // Monitors the app launch times
|
||||
|
||||
// Only ask to rate if the user has a suitable store
|
||||
AppRate.showRateDialogIfMeetsConditions(this); // Shows the Rate Dialog when conditions are met
|
||||
AppRate.showRateDialogIfMeetsConditions(this) // Shows the Rate Dialog when conditions are met
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -596,7 +596,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
filter.addAction(MeshService.actionReceived(Portnums.PortNum.TEXT_MESSAGE_APP_VALUE))
|
||||
filter.addAction((MeshService.ACTION_MESSAGE_STATUS))
|
||||
registerReceiver(meshServiceReceiver, filter)
|
||||
receiverRegistered = true;
|
||||
receiverRegistered = true
|
||||
}
|
||||
|
||||
private fun unregisterMeshReceiver() {
|
||||
|
@ -1091,7 +1091,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
applicationContext.contentResolver.openFileDescriptor(file_uri, "w")?.use {
|
||||
FileOutputStream(it.fileDescriptor).use { fs ->
|
||||
// Write header
|
||||
fs.write(("from,rssi,snr,time,dist\n").toByteArray());
|
||||
fs.write(("from,rssi,snr,time,dist\n").toByteArray())
|
||||
// Packets are ordered by time, we keep most recent position of
|
||||
// our device in my_position.
|
||||
var my_position: MeshProtos.Position? = null
|
||||
|
@ -1102,8 +1102,12 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
my_position = position
|
||||
} else if (my_position != null) {
|
||||
val dist = positionToMeter(my_position!!, position).roundToInt()
|
||||
fs.write("%x,%d,%f,%d,%d\n".format(packet_proto.from,packet_proto.rxRssi,
|
||||
packet_proto.rxSnr, packet_proto.rxTime, dist).toByteArray())
|
||||
fs.write(
|
||||
"%x,%d,%f,%d,%d\n".format(
|
||||
packet_proto.from, packet_proto.rxRssi,
|
||||
packet_proto.rxSnr, packet_proto.rxTime, dist
|
||||
).toByteArray()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,13 +37,13 @@ class MeshUtilApplication : GeeksvilleApplication() {
|
|||
}
|
||||
|
||||
fun sendCrashReports() {
|
||||
if(isAnalyticsAllowed)
|
||||
if (isAnalyticsAllowed)
|
||||
crashlytics.sendUnsentReports()
|
||||
}
|
||||
|
||||
// Send any old reports if user approves
|
||||
sendCrashReports()
|
||||
|
||||
|
||||
// Attach to our exception wrapper
|
||||
Exceptions.reporter = { exception, _, _ ->
|
||||
crashlytics.recordException(exception)
|
||||
|
|
|
@ -32,8 +32,7 @@ data class MyNodeInfo(
|
|||
parcel.readInt(),
|
||||
parcel.readInt(),
|
||||
parcel.readInt()
|
||||
) {
|
||||
}
|
||||
)
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(myNodeNum)
|
||||
|
|
|
@ -18,7 +18,8 @@ data class Channel(
|
|||
)
|
||||
|
||||
private val cleartextPSK = ByteString.EMPTY
|
||||
private val defaultPSK = byteArrayOfInts(1) // a shortstring code to indicate we need our default PSK
|
||||
private val defaultPSK =
|
||||
byteArrayOfInts(1) // a shortstring code to indicate we need our default PSK
|
||||
|
||||
// TH=he unsecured channel that devices ship with
|
||||
val defaultChannel = Channel(
|
||||
|
@ -55,7 +56,7 @@ data class Channel(
|
|||
val pskIndex = settings.psk.byteAt(0).toInt()
|
||||
|
||||
if (pskIndex == 0)
|
||||
cleartextPSK
|
||||
cleartextPSK
|
||||
else {
|
||||
// Treat an index of 1 as the old channelDefaultKey and work up from there
|
||||
val bytes = channelDefaultKey.clone()
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
package com.geeksville.mesh.model
|
||||
|
||||
import com.geeksville.mesh.ChannelProtos
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.R
|
||||
|
||||
enum class ChannelOption(val modemConfig: ChannelProtos.ChannelSettings.ModemConfig, val configRes: Int, val minBroadcastPeriodSecs: Int) {
|
||||
enum class ChannelOption(
|
||||
val modemConfig: ChannelProtos.ChannelSettings.ModemConfig,
|
||||
val configRes: Int,
|
||||
val minBroadcastPeriodSecs: Int
|
||||
) {
|
||||
SHORT(ChannelProtos.ChannelSettings.ModemConfig.Bw500Cr45Sf128, R.string.modem_config_short, 3),
|
||||
MEDIUM(ChannelProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128, R.string.modem_config_medium, 12),
|
||||
LONG(ChannelProtos.ChannelSettings.ModemConfig.Bw31_25Cr48Sf512, R.string.modem_config_long, 240),
|
||||
VERY_LONG(ChannelProtos.ChannelSettings.ModemConfig.Bw125Cr48Sf4096, R.string.modem_config_very_long, 375);
|
||||
MEDIUM(
|
||||
ChannelProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128,
|
||||
R.string.modem_config_medium,
|
||||
12
|
||||
),
|
||||
LONG(
|
||||
ChannelProtos.ChannelSettings.ModemConfig.Bw31_25Cr48Sf512,
|
||||
R.string.modem_config_long,
|
||||
240
|
||||
),
|
||||
VERY_LONG(
|
||||
ChannelProtos.ChannelSettings.ModemConfig.Bw125Cr48Sf4096,
|
||||
R.string.modem_config_very_long,
|
||||
375
|
||||
);
|
||||
|
||||
companion object {
|
||||
fun fromConfig(modemConfig: ChannelProtos.ChannelSettings.ModemConfig?): ChannelOption? {
|
||||
|
@ -18,6 +33,7 @@ enum class ChannelOption(val modemConfig: ChannelProtos.ChannelSettings.ModemCon
|
|||
}
|
||||
return null
|
||||
}
|
||||
|
||||
val defaultMinBroadcastPeriod = VERY_LONG.minBroadcastPeriodSecs
|
||||
}
|
||||
}
|
|
@ -4,8 +4,6 @@ import android.graphics.Bitmap
|
|||
import android.net.Uri
|
||||
import android.util.Base64
|
||||
import com.geeksville.mesh.AppOnlyProtos
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.google.protobuf.ByteString
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import com.google.zxing.MultiFormatWriter
|
||||
import com.journeyapps.barcodescanner.BarcodeEncoder
|
||||
|
@ -42,11 +40,12 @@ data class ChannelSet(
|
|||
/**
|
||||
* Return the primary channel info
|
||||
*/
|
||||
val primaryChannel: Channel? get() =
|
||||
if(protobuf.settingsCount > 0)
|
||||
Channel(protobuf.getSettings(0))
|
||||
else
|
||||
null
|
||||
val primaryChannel: Channel?
|
||||
get() =
|
||||
if (protobuf.settingsCount > 0)
|
||||
Channel(protobuf.getSettings(0))
|
||||
else
|
||||
null
|
||||
|
||||
/// Return an URL that represents the current channel values
|
||||
/// @param upperCasePrefix - portions of the URL can be upper case to make for more efficient QR codes
|
||||
|
@ -56,7 +55,7 @@ data class ChannelSet(
|
|||
val channelBytes = protobuf.toByteArray() ?: ByteArray(0) // if unset just use empty
|
||||
val enc = Base64.encodeToString(channelBytes, base64Flags)
|
||||
|
||||
val p = if(upperCasePrefix)
|
||||
val p = if (upperCasePrefix)
|
||||
prefix.toUpperCase()
|
||||
else
|
||||
prefix
|
||||
|
@ -68,7 +67,12 @@ data class ChannelSet(
|
|||
|
||||
// We encode as UPPER case for the QR code URL because QR codes are more efficient for that special case
|
||||
val bitMatrix =
|
||||
multiFormatWriter.encode(getChannelUrl(true).toString(), BarcodeFormat.QR_CODE, 192, 192);
|
||||
multiFormatWriter.encode(
|
||||
getChannelUrl(true).toString(),
|
||||
BarcodeFormat.QR_CODE,
|
||||
192,
|
||||
192
|
||||
)
|
||||
val barcodeEncoder = BarcodeEncoder()
|
||||
return barcodeEncoder.createBitmap(bitMatrix)
|
||||
}
|
||||
|
|
|
@ -5,14 +5,15 @@ import com.geeksville.android.Logging
|
|||
/**
|
||||
* Provide structured access to parse and compare device version strings
|
||||
*/
|
||||
data class DeviceVersion(val asString: String): Comparable<DeviceVersion>, Logging {
|
||||
data class DeviceVersion(val asString: String) : Comparable<DeviceVersion>, Logging {
|
||||
|
||||
val asInt get() = try {
|
||||
verStringToInt(asString)
|
||||
} catch(e: Exception) {
|
||||
warn("Exception while parsing version '$asString', assuming version 0")
|
||||
0
|
||||
}
|
||||
val asInt
|
||||
get() = try {
|
||||
verStringToInt(asString)
|
||||
} catch (e: Exception) {
|
||||
warn("Exception while parsing version '$asString', assuming version 0")
|
||||
0
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a version string of the form 1.23.57 to a comparable integer of
|
||||
|
|
|
@ -12,7 +12,9 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.mesh.*
|
||||
import com.geeksville.mesh.IMeshService
|
||||
import com.geeksville.mesh.MyNodeInfo
|
||||
import com.geeksville.mesh.RadioConfigProtos
|
||||
import com.geeksville.mesh.database.MeshtasticDatabase
|
||||
import com.geeksville.mesh.database.PacketRepository
|
||||
import com.geeksville.mesh.database.entity.Packet
|
||||
|
@ -135,7 +137,8 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging
|
|||
}
|
||||
|
||||
var region: RadioConfigProtos.RegionCode
|
||||
get() = meshService?.region?.let { RadioConfigProtos.RegionCode.forNumber(it) } ?: RadioConfigProtos.RegionCode.Unset
|
||||
get() = meshService?.region?.let { RadioConfigProtos.RegionCode.forNumber(it) }
|
||||
?: RadioConfigProtos.RegionCode.Unset
|
||||
set(value) {
|
||||
meshService?.region = value.number
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ import java.util.*
|
|||
|
||||
open class BLEException(msg: String) : IOException(msg)
|
||||
|
||||
open class BLECharacteristicNotFoundException(uuid: UUID) : BLEException("Can't get characteristic $uuid")
|
||||
open class BLECharacteristicNotFoundException(uuid: UUID) :
|
||||
BLEException("Can't get characteristic $uuid")
|
||||
|
||||
/// Our interface is being shut down
|
||||
open class BLEConnectionClosing() : BLEException("Connection closing ")
|
||||
open class BLEConnectionClosing : BLEException("Connection closing ")
|
|
@ -479,8 +479,7 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String
|
|||
|
||||
try {
|
||||
s?.close()
|
||||
}
|
||||
catch(_: BLEConnectionClosing) {
|
||||
} catch (_: BLEConnectionClosing) {
|
||||
warn("Ignoring BLE errors while closing")
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -26,5 +26,9 @@ class BluetoothStateReceiver(
|
|||
}
|
||||
}
|
||||
|
||||
private val Intent.bluetoothAdapterState: Int get() = getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
|
||||
private val Intent.bluetoothAdapterState: Int
|
||||
get() = getIntExtra(
|
||||
BluetoothAdapter.EXTRA_STATE,
|
||||
-1
|
||||
)
|
||||
}
|
|
@ -1392,7 +1392,7 @@ class MeshService : Service(), Logging {
|
|||
private fun fixupChannelList(lIn: List<ChannelProtos.Channel>): Array<ChannelProtos.Channel> {
|
||||
// When updating old firmware, we will briefly be told that there is zero channels
|
||||
val maxChannels =
|
||||
max(myNodeInfo?.maxChannels ?: 8, 1) // If we don't have my node info, assume 8 channels
|
||||
max(myNodeInfo?.maxChannels ?: 8, 1) // If we don't have my node info, assume 8 channels
|
||||
var l = lIn
|
||||
while (l.size < maxChannels) {
|
||||
val b = ChannelProtos.Channel.newBuilder()
|
||||
|
@ -1561,7 +1561,7 @@ class MeshService : Service(), Logging {
|
|||
) {
|
||||
try {
|
||||
val mi = myNodeInfo
|
||||
if(mi != null) {
|
||||
if (mi != null) {
|
||||
debug("Sending our position/time to=$destNum lat=$lat, lon=$lon, alt=$alt")
|
||||
|
||||
val position = MeshProtos.Position.newBuilder().also {
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Intent
|
|||
import android.os.Parcelable
|
||||
import com.geeksville.mesh.DataPacket
|
||||
import com.geeksville.mesh.NodeInfo
|
||||
import com.geeksville.mesh.Portnums
|
||||
|
||||
class MeshServiceBroadcasts(
|
||||
private val context: Context,
|
||||
|
@ -18,7 +17,12 @@ class MeshServiceBroadcasts(
|
|||
*/
|
||||
fun broadcastReceivedData(payload: DataPacket) {
|
||||
|
||||
explicitBroadcast(Intent(MeshService.actionReceived(payload.dataType)).putExtra(EXTRA_PAYLOAD, payload))
|
||||
explicitBroadcast(
|
||||
Intent(MeshService.actionReceived(payload.dataType)).putExtra(
|
||||
EXTRA_PAYLOAD,
|
||||
payload
|
||||
)
|
||||
)
|
||||
|
||||
/*
|
||||
// For the time being we ALSO broadcast using old ACTION_RECEIVED_DATA field for any oldschool opaque packets
|
||||
|
|
|
@ -39,7 +39,8 @@ class MeshServiceLocationCallback(
|
|||
|
||||
try {
|
||||
// Do we want to broadcast this position globally, or are we just telling the local node what its current position is (
|
||||
val shouldBroadcast = true // no need to rate limit, because we are just sending at the interval requested by the preferences
|
||||
val shouldBroadcast =
|
||||
true // no need to rate limit, because we are just sending at the interval requested by the preferences
|
||||
val destinationNumber =
|
||||
if (shouldBroadcast) DataPacket.NODENUM_BROADCAST else getNodeNum()
|
||||
|
||||
|
|
|
@ -16,12 +16,9 @@ import androidx.annotation.RequiresApi
|
|||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import com.geeksville.mesh.DataPacket
|
||||
import com.geeksville.mesh.MainActivity
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.android.notificationManager
|
||||
import com.geeksville.mesh.ui.SLogging
|
||||
import com.geeksville.mesh.utf8
|
||||
import java.io.Closeable
|
||||
|
||||
|
||||
|
@ -29,6 +26,7 @@ class MeshServiceNotifications(
|
|||
private val context: Context
|
||||
) : Closeable {
|
||||
private val notificationManager: NotificationManager get() = context.notificationManager
|
||||
|
||||
// We have two notification channels: one for general service status and another one for messages
|
||||
val notifyId = 101
|
||||
private val messageNotifyId = 102
|
||||
|
@ -96,12 +94,16 @@ class MeshServiceNotifications(
|
|||
}
|
||||
|
||||
fun updateServiceStateNotification(summaryString: String) =
|
||||
notificationManager.notify(notifyId,
|
||||
createServiceStateNotification(summaryString))
|
||||
notificationManager.notify(
|
||||
notifyId,
|
||||
createServiceStateNotification(summaryString)
|
||||
)
|
||||
|
||||
fun updateMessageNotification(name: String, message: String) =
|
||||
notificationManager.notify(messageNotifyId,
|
||||
createMessageNotifcation(name, message))
|
||||
notificationManager.notify(
|
||||
messageNotifyId,
|
||||
createMessageNotifcation(name, message)
|
||||
)
|
||||
|
||||
private val openAppIntent: PendingIntent by lazy {
|
||||
PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), 0)
|
||||
|
@ -126,7 +128,7 @@ class MeshServiceNotifications(
|
|||
return bitmap
|
||||
}
|
||||
|
||||
fun commonBuilder(channel: String) : NotificationCompat.Builder {
|
||||
fun commonBuilder(channel: String): NotificationCompat.Builder {
|
||||
val builder = NotificationCompat.Builder(context, channel)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setContentIntent(openAppIntent)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package com.geeksville.mesh.service
|
||||
|
||||
import com.geeksville.mesh.*
|
||||
import com.geeksville.mesh.DataPacket
|
||||
import com.geeksville.mesh.MyNodeInfo
|
||||
import com.geeksville.mesh.NodeInfo
|
||||
import com.geeksville.mesh.RadioConfigProtos
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/// Our saved preferences as stored on disk
|
||||
|
|
|
@ -3,18 +3,14 @@ package com.geeksville.mesh.service
|
|||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.work.BackoffPolicy
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.*
|
||||
import com.geeksville.andlib.BuildConfig
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Helper that calls MeshService.startService()
|
||||
*/
|
||||
public class ServiceStarter(
|
||||
class ServiceStarter(
|
||||
appContext: Context,
|
||||
workerParams: WorkerParameters
|
||||
) : Worker(appContext, workerParams) {
|
||||
|
|
|
@ -14,7 +14,7 @@ class NopInterface : IRadioInterface {
|
|||
}
|
||||
}
|
||||
|
||||
override fun handleSendToRadio(p: ByteArray) {
|
||||
override fun handleSendToRadio(p: ByteArray) {
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
|
|
|
@ -26,7 +26,6 @@ open class RadioNotConnectedException(message: String = "Not connected to radio"
|
|||
BLEException(message)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Handles the bluetooth link with a mesh radio device. Does not cache any device state,
|
||||
* just does bluetooth comms etc...
|
||||
|
@ -77,7 +76,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
var address = prefs.getString(DEVADDR_KEY, null)
|
||||
|
||||
// If we are running on the emulator we default to the mock interface, so we can have some data to show to the user
|
||||
if(address == null && isMockInterfaceAvailable(context))
|
||||
if (address == null && isMockInterfaceAvailable(context))
|
||||
address = MockInterface.prefix.toString()
|
||||
|
||||
return address
|
||||
|
@ -86,7 +85,8 @@ class RadioInterfaceService : Service(), Logging {
|
|||
/** return true if we should show the mock interface on this device
|
||||
* (ie are we in an emulator or in testlab
|
||||
*/
|
||||
fun isMockInterfaceAvailable(context: Context) = isEmulator || ((context.applicationContext as GeeksvilleApplication).isInTestLab)
|
||||
fun isMockInterfaceAvailable(context: Context) =
|
||||
isEmulator || ((context.applicationContext as GeeksvilleApplication).isInTestLab)
|
||||
|
||||
/** Like getDeviceAddress, but filtered to return only devices we are currently bonded with
|
||||
*
|
||||
|
@ -204,7 +204,7 @@ class RadioInterfaceService : Service(), Logging {
|
|||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
return binder;
|
||||
return binder
|
||||
}
|
||||
|
||||
|
||||
|
@ -227,8 +227,8 @@ class RadioInterfaceService : Service(), Logging {
|
|||
|
||||
val c = address[0]
|
||||
val rest = address.substring(1)
|
||||
radioIf = InterfaceFactory.getFactory(c)?.createInterface(this, rest) ?:
|
||||
NopInterface()
|
||||
radioIf =
|
||||
InterfaceFactory.getFactory(c)?.createInterface(this, rest) ?: NopInterface()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD
|
|||
if (reliable != null)
|
||||
if (!characteristic.value.contentEquals(reliable)) {
|
||||
errormsg("A reliable write failed!")
|
||||
gatt.abortReliableWrite();
|
||||
gatt.abortReliableWrite()
|
||||
completeWork(
|
||||
STATUS_RELIABLE_WRITE_FAILED,
|
||||
characteristic
|
||||
|
|
|
@ -17,7 +17,7 @@ import java.util.zip.CRC32
|
|||
/**
|
||||
* Some misformatted ESP32s have problems
|
||||
*/
|
||||
class DeviceRejectedException() : BLEException("Device rejected filesize")
|
||||
class DeviceRejectedException : BLEException("Device rejected filesize")
|
||||
|
||||
/**
|
||||
* Move this somewhere as a generic network byte order function
|
||||
|
@ -389,7 +389,7 @@ class SoftwareUpdateService : JobIntentService(), Logging {
|
|||
)
|
||||
if (progress != oldProgress) {
|
||||
debug("sending block ${progress}%")
|
||||
oldProgress = progress;
|
||||
oldProgress = progress
|
||||
}
|
||||
var blockSize = 512 - 3 // Max size MTU excluding framing
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.geeksville.mesh.service
|
||||
|
||||
import com.geeksville.android.Logging
|
||||
import java.io.*
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.net.InetAddress
|
||||
import java.net.Socket
|
||||
import kotlin.concurrent.thread
|
||||
|
@ -21,7 +24,7 @@ class TCPInterface(service: RadioInterfaceService, private val address: String)
|
|||
}
|
||||
}
|
||||
|
||||
var socket: Socket? = null
|
||||
var socket: Socket? = null
|
||||
lateinit var outStream: OutputStream
|
||||
lateinit var inStream: InputStream
|
||||
|
||||
|
@ -30,7 +33,7 @@ class TCPInterface(service: RadioInterfaceService, private val address: String)
|
|||
}
|
||||
|
||||
override fun sendBytes(p: ByteArray) {
|
||||
outStream.write(p)
|
||||
outStream.write(p)
|
||||
}
|
||||
|
||||
override fun flushBytes() {
|
||||
|
@ -39,7 +42,7 @@ class TCPInterface(service: RadioInterfaceService, private val address: String)
|
|||
|
||||
override fun onDeviceDisconnect(waitForStopped: Boolean) {
|
||||
val s = socket
|
||||
if(s != null) {
|
||||
if (s != null) {
|
||||
socket = null
|
||||
outStream.close()
|
||||
inStream.close()
|
||||
|
@ -68,15 +71,14 @@ class TCPInterface(service: RadioInterfaceService, private val address: String)
|
|||
// No need to keep a reference to this thread - it will exit when we close inStream
|
||||
thread(start = true, isDaemon = true, name = "TCP reader") {
|
||||
try {
|
||||
while(true) {
|
||||
while (true) {
|
||||
val c = inStream.read()
|
||||
if(c == -1)
|
||||
break;
|
||||
if (c == -1)
|
||||
break
|
||||
else
|
||||
readChar(c.toByte())
|
||||
}
|
||||
}
|
||||
catch(ex: Throwable) {
|
||||
} catch (ex: Throwable) {
|
||||
errormsg("Exception in TCP reader: $ex")
|
||||
onDeviceDisconnect(false)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.geeksville.mesh.model.UIViewModel
|
|||
class DebugFragment : Fragment() {
|
||||
|
||||
private var _binding: DebugFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
|
@ -44,11 +45,11 @@ class DebugFragment : Fragment() {
|
|||
model.deleteAllPacket()
|
||||
}
|
||||
|
||||
binding.closeButton.setOnClickListener{
|
||||
parentFragmentManager.popBackStack();
|
||||
binding.closeButton.setOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
}
|
||||
model.allPackets.observe(viewLifecycleOwner, Observer {
|
||||
packets -> packets?.let { adapter.setPackets(it) }
|
||||
model.allPackets.observe(viewLifecycleOwner, Observer { packets ->
|
||||
packets?.let { adapter.setPackets(it) }
|
||||
})
|
||||
}
|
||||
}
|
|
@ -131,8 +131,10 @@ fun positionToMeter(a: MeshProtos.Position, b: MeshProtos.Position): Double {
|
|||
a.latitudeI * 1e-7,
|
||||
a.longitudeI * 1e-7,
|
||||
b.latitudeI * 1e-7,
|
||||
b.longitudeI * 1e-7)
|
||||
b.longitudeI * 1e-7
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert degrees/mins/secs to a single double
|
||||
*
|
||||
|
@ -186,7 +188,7 @@ fun bearing(
|
|||
val y = sin(deltaLonRad) * cos(lat2Rad)
|
||||
val x =
|
||||
cos(lat1Rad) * sin(lat2Rad) - (sin(lat1Rad) * cos(lat2Rad)
|
||||
* Math.cos(deltaLonRad))
|
||||
* Math.cos(deltaLonRad))
|
||||
return radToBearing(Math.atan2(y, x))
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.geeksville.android.Logging
|
||||
import com.geeksville.mesh.DataPacket
|
||||
import com.geeksville.mesh.MessageStatus
|
||||
import com.geeksville.mesh.NodeInfo
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.databinding.AdapterMessageLayoutBinding
|
||||
import com.geeksville.mesh.databinding.MessagesFragmentBinding
|
||||
|
@ -25,7 +24,6 @@ import com.geeksville.mesh.model.UIViewModel
|
|||
import com.geeksville.mesh.service.MeshService
|
||||
import com.google.android.material.chip.Chip
|
||||
import java.text.DateFormat
|
||||
import java.text.ParseException
|
||||
import java.util.*
|
||||
|
||||
// Allows usage like email.on(EditorInfo.IME_ACTION_NEXT, { confirm() })
|
||||
|
@ -54,9 +52,9 @@ class MessagesFragment : ScreenFragment("Messages"), Logging {
|
|||
private val timeFormat: DateFormat =
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT)
|
||||
|
||||
private fun getShortDateTime(time : Date): String {
|
||||
private fun getShortDateTime(time: Date): String {
|
||||
// return time if within 24 hours, otherwise date/time
|
||||
val one_day = 60*60*24*100L
|
||||
val one_day = 60 * 60 * 24 * 100L
|
||||
if (System.currentTimeMillis() - time.time > one_day) {
|
||||
return dateTimeFormat.format(time)
|
||||
} else return timeFormat.format(time)
|
||||
|
@ -152,11 +150,25 @@ class MessagesFragment : ScreenFragment("Messages"), Logging {
|
|||
if (isMe) {
|
||||
marginParams.leftMargin = messageOffset
|
||||
marginParams.rightMargin = 0
|
||||
context?.let{ holder.card.setCardBackgroundColor(ContextCompat.getColor(it, R.color.colorMyMsg)) }
|
||||
context?.let {
|
||||
holder.card.setCardBackgroundColor(
|
||||
ContextCompat.getColor(
|
||||
it,
|
||||
R.color.colorMyMsg
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
marginParams.rightMargin = messageOffset
|
||||
marginParams.leftMargin = 0
|
||||
context?.let{ holder.card.setCardBackgroundColor(ContextCompat.getColor(it, R.color.colorMsg)) }
|
||||
context?.let {
|
||||
holder.card.setCardBackgroundColor(
|
||||
ContextCompat.getColor(
|
||||
it,
|
||||
R.color.colorMsg
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
// Hide the username chip for my messages
|
||||
if (isMe) {
|
||||
|
@ -240,20 +252,23 @@ class MessagesFragment : ScreenFragment("Messages"), Logging {
|
|||
// If connection state _OR_ myID changes we have to fix our ability to edit outgoing messages
|
||||
fun updateTextEnabled() {
|
||||
binding.textInputLayout.isEnabled =
|
||||
model.isConnected.value != MeshService.ConnectionState.DISCONNECTED && model.nodeDB.myId.value != null && model.radioConfig.value != null
|
||||
model.isConnected.value != MeshService.ConnectionState.DISCONNECTED && model.nodeDB.myId.value != null && model.radioConfig.value != null
|
||||
}
|
||||
|
||||
model.isConnected.observe(viewLifecycleOwner, Observer { _ ->
|
||||
// If we don't know our node ID and we are offline don't let user try to send
|
||||
updateTextEnabled() })
|
||||
updateTextEnabled()
|
||||
})
|
||||
|
||||
model.nodeDB.myId.observe(viewLifecycleOwner, Observer { _ ->
|
||||
// If we don't know our node ID and we are offline don't let user try to send
|
||||
updateTextEnabled() })
|
||||
updateTextEnabled()
|
||||
})
|
||||
|
||||
model.radioConfig.observe(viewLifecycleOwner, Observer { _ ->
|
||||
// If we don't know our node ID and we are offline don't let user try to send
|
||||
updateTextEnabled() })
|
||||
updateTextEnabled()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,49 +1,50 @@
|
|||
package com.geeksville.mesh.ui
|
||||
|
||||
import android.content.Context
|
||||
import java.text.DateFormat
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.database.entity.Packet
|
||||
import java.util.*
|
||||
|
||||
class PacketListAdapter internal constructor(
|
||||
context: Context
|
||||
) : RecyclerView.Adapter<PacketListAdapter.PacketViewHolder>() {
|
||||
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
private var packets = emptyList<Packet>()
|
||||
|
||||
private val timeFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM)
|
||||
|
||||
inner class PacketViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val packetTypeView: TextView = itemView.findViewById(R.id.type)
|
||||
val packetDateReceivedView: TextView = itemView.findViewById(R.id.dateReceived)
|
||||
val packetRawMessage : TextView = itemView.findViewById(R.id.rawMessage)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PacketViewHolder {
|
||||
val itemView = inflater.inflate(R.layout.adapter_packet_layout, parent, false)
|
||||
return PacketViewHolder(itemView)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PacketViewHolder, position: Int) {
|
||||
val current = packets[position]
|
||||
holder.packetTypeView.text = current.message_type
|
||||
holder.packetRawMessage.text = current.raw_message
|
||||
val date = Date(current.received_date)
|
||||
holder.packetDateReceivedView.text = timeFormat.format(date)
|
||||
}
|
||||
|
||||
internal fun setPackets(packets: List<Packet>) {
|
||||
this.packets = packets
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun getItemCount() = packets.size
|
||||
|
||||
package com.geeksville.mesh.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.database.entity.Packet
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
class PacketListAdapter internal constructor(
|
||||
context: Context
|
||||
) : RecyclerView.Adapter<PacketListAdapter.PacketViewHolder>() {
|
||||
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
private var packets = emptyList<Packet>()
|
||||
|
||||
private val timeFormat: DateFormat =
|
||||
DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM)
|
||||
|
||||
inner class PacketViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val packetTypeView: TextView = itemView.findViewById(R.id.type)
|
||||
val packetDateReceivedView: TextView = itemView.findViewById(R.id.dateReceived)
|
||||
val packetRawMessage: TextView = itemView.findViewById(R.id.rawMessage)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PacketViewHolder {
|
||||
val itemView = inflater.inflate(R.layout.adapter_packet_layout, parent, false)
|
||||
return PacketViewHolder(itemView)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PacketViewHolder, position: Int) {
|
||||
val current = packets[position]
|
||||
holder.packetTypeView.text = current.message_type
|
||||
holder.packetRawMessage.text = current.raw_message
|
||||
val date = Date(current.received_date)
|
||||
holder.packetDateReceivedView.text = timeFormat.format(date)
|
||||
}
|
||||
|
||||
internal fun setPackets(packets: List<Packet>) {
|
||||
this.packets = packets
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun getItemCount() = packets.size
|
||||
|
||||
}
|
|
@ -59,7 +59,7 @@ import kotlinx.coroutines.Job
|
|||
import java.util.regex.Pattern
|
||||
|
||||
|
||||
object SLogging : Logging {}
|
||||
object SLogging : Logging
|
||||
|
||||
/// Change to a new macaddr selection, updating GUI and radio
|
||||
fun changeDeviceSelection(context: MainActivity, newAddr: String?) {
|
||||
|
@ -186,7 +186,7 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
|||
// if that device later disconnects remove it as a candidate
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
|
||||
if ((result.device.name?.startsWith("Mesh") ?: false)) {
|
||||
if ((result.device.name?.startsWith("Mesh") == true)) {
|
||||
val addr = result.device.address
|
||||
val fullAddr = "x$addr" // full address with the bluetooh prefix
|
||||
// prevent logspam because weill get get lots of redundant scan results
|
||||
|
@ -727,7 +727,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
scanModel.onSelected(requireActivity() as MainActivity, device)
|
||||
|
||||
if (!b.isSelected)
|
||||
binding.scanStatusText.setText(getString(R.string.please_pair))
|
||||
binding.scanStatusText.text = getString(R.string.please_pair)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ class UsersFragment : ScreenFragment("Users"), Logging {
|
|||
val name = n.user?.longName ?: n.user?.id ?: "Unknown node"
|
||||
holder.nodeNameView.text = name
|
||||
|
||||
val pos = n.validPosition;
|
||||
val pos = n.validPosition
|
||||
if (pos != null) {
|
||||
val coords =
|
||||
String.format("%.5f %.5f", pos.latitude, pos.longitude).replace(",", ".")
|
||||
|
@ -141,7 +141,7 @@ class UsersFragment : ScreenFragment("Users"), Logging {
|
|||
}
|
||||
renderBattery(n.batteryPctLevel, holder)
|
||||
|
||||
holder.lastTime.text = formatAgo(n.lastHeard);
|
||||
holder.lastTime.text = formatAgo(n.lastHeard)
|
||||
|
||||
if ((n.num == ourNodeInfo?.num) || (n.snr > 100f)) {
|
||||
holder.signalView.visibility = View.INVISIBLE
|
||||
|
|
Ładowanie…
Reference in New Issue