kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
rodzic
056d4a5829
commit
fe56d257f5
|
@ -62,10 +62,11 @@ data class DataPacket(
|
|||
* If this is a text message, return the string, otherwise null
|
||||
*/
|
||||
val text: String?
|
||||
get() = if (dataType == Portnums.PortNum.TEXT_MESSAGE_APP_VALUE)
|
||||
get() = if (dataType == Portnums.PortNum.TEXT_MESSAGE_APP_VALUE) {
|
||||
bytes?.decodeToString()
|
||||
else
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
constructor(to: String?, channel: Int, waypoint: MeshProtos.Waypoint) : this(
|
||||
to = to,
|
||||
|
@ -75,10 +76,11 @@ data class DataPacket(
|
|||
)
|
||||
|
||||
val waypoint: MeshProtos.Waypoint?
|
||||
get() = if (dataType == Portnums.PortNum.WAYPOINT_APP_VALUE)
|
||||
get() = if (dataType == Portnums.PortNum.WAYPOINT_APP_VALUE) {
|
||||
MeshProtos.Waypoint.parseFrom(bytes)
|
||||
else
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
// Autogenerated comparision, because we have a byte array
|
||||
|
||||
|
@ -142,7 +144,7 @@ data class DataPacket(
|
|||
return 0
|
||||
}
|
||||
|
||||
/// Update our object from our parcel (used for inout parameters
|
||||
// Update our object from our parcel (used for inout parameters
|
||||
fun readFromParcel(parcel: Parcel) {
|
||||
to = parcel.readString()
|
||||
parcel.createByteArray()
|
||||
|
@ -164,7 +166,7 @@ data class DataPacket(
|
|||
/** The Node ID for the local node - used for from when sender doesn't know our local node ID */
|
||||
const val ID_LOCAL = "^local"
|
||||
|
||||
/// special broadcast address
|
||||
// special broadcast address
|
||||
const val NODENUM_BROADCAST = (0xffffffff).toInt()
|
||||
|
||||
// Public-key cryptography (PKC) channel index
|
||||
|
@ -181,4 +183,4 @@ data class DataPacket(
|
|||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
tab.icon = ContextCompat.getDrawable(this, tabInfos[position].icon)
|
||||
}.attach()
|
||||
|
||||
binding.tabLayout.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {
|
||||
binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
val mainTab = tab?.position ?: 0
|
||||
model.setCurrentTab(mainTab)
|
||||
|
@ -254,7 +254,7 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
|
||||
private var requestedChannelUrl: Uri? = null
|
||||
|
||||
/// Handle any itents that were passed into us
|
||||
// Handle any intents that were passed into us
|
||||
private fun handleIntent(intent: Intent) {
|
||||
val appLinkAction = intent.action
|
||||
val appLinkData: Uri? = intent.data
|
||||
|
@ -327,7 +327,7 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
showSettingsPage() // Default to the settings page in this case
|
||||
}
|
||||
|
||||
/// Called when we gain/lose a connection to our mesh radio
|
||||
// Called when we gain/lose a connection to our mesh radio
|
||||
private fun onMeshConnectionChanged(newConnection: MeshService.ConnectionState) {
|
||||
if (newConnection == MeshService.ConnectionState.CONNECTED) {
|
||||
serviceRepository.meshService?.let { service ->
|
||||
|
@ -336,17 +336,17 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
|
||||
if (info != null) {
|
||||
val isOld = info.minAppVersion > BuildConfig.VERSION_CODE
|
||||
if (isOld)
|
||||
if (isOld) {
|
||||
showAlert(R.string.app_too_old, R.string.must_update)
|
||||
else {
|
||||
} else {
|
||||
// If we are already doing an update don't put up a dialog or try to get device info
|
||||
val isUpdating = service.updateStatus >= 0
|
||||
if (!isUpdating) {
|
||||
val curVer = DeviceVersion(info.firmwareVersion ?: "0.0.0")
|
||||
|
||||
if (curVer < MeshService.minDeviceVersion)
|
||||
if (curVer < MeshService.minDeviceVersion) {
|
||||
showAlert(R.string.firmware_too_old, R.string.firmware_old)
|
||||
else {
|
||||
} else {
|
||||
// If our app is too old/new, we probably don't understand the new DeviceConfig messages, so we don't read them until here
|
||||
|
||||
// we have a connection to our device now, do the channel change
|
||||
|
@ -359,8 +359,9 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
warn("Abandoning connect $ex, because we probably just lost device connection")
|
||||
}
|
||||
// if provideLocation enabled: Start providing location (from phone GPS) to mesh
|
||||
if (model.provideLocation.value == true)
|
||||
if (model.provideLocation.value == true) {
|
||||
service.startProvideLocation()
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasNotificationPermission()) {
|
||||
|
@ -406,9 +407,9 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
val channels = url.toChannelSet()
|
||||
val shouldAdd = url.shouldAddChannels()
|
||||
val primary = channels.primaryChannel
|
||||
if (primary == null)
|
||||
if (primary == null) {
|
||||
showSnackbar(R.string.channel_invalid)
|
||||
else {
|
||||
} else {
|
||||
val dialogMessage = if (!shouldAdd) {
|
||||
getString(R.string.do_you_want_switch).format(primary.name)
|
||||
} else {
|
||||
|
@ -651,10 +652,11 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
handler.postDelayed({ postPing() }, 30000)
|
||||
}
|
||||
item.isChecked = !item.isChecked // toggle ping test
|
||||
if (item.isChecked)
|
||||
if (item.isChecked) {
|
||||
postPing()
|
||||
else
|
||||
} else {
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
return true
|
||||
}
|
||||
R.id.radio_config -> {
|
||||
|
@ -705,11 +707,11 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/// Theme functions
|
||||
// Theme functions
|
||||
|
||||
private fun chooseThemeDialog() {
|
||||
|
||||
/// Prepare dialog and its items
|
||||
// Prepare dialog and its items
|
||||
val builder = MaterialAlertDialogBuilder(this)
|
||||
builder.setTitle(getString(R.string.choose_theme))
|
||||
|
||||
|
@ -719,7 +721,7 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
getString(R.string.theme_system) to AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
)
|
||||
|
||||
/// Load preferences and its value
|
||||
// Load preferences and its value
|
||||
val prefs = UIViewModel.getPreferences(this)
|
||||
val theme = prefs.getInt("theme", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
debug("Theme from prefs: $theme")
|
||||
|
@ -740,13 +742,13 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
}
|
||||
|
||||
private fun chooseLangDialog() {
|
||||
/// Prepare dialog and its items
|
||||
// Prepare dialog and its items
|
||||
val builder = MaterialAlertDialogBuilder(this)
|
||||
builder.setTitle(getString(R.string.preferences_language))
|
||||
|
||||
val languageTags = LanguageUtils.getLanguageTags(this)
|
||||
|
||||
/// Load preferences and its value
|
||||
// Load preferences and its value
|
||||
val lang = LanguageUtils.getLocale()
|
||||
debug("Lang from prefs: $lang")
|
||||
|
||||
|
|
|
@ -150,8 +150,9 @@ fun Context.hasLocationPermission() = getLocationPermissions().isEmpty()
|
|||
*/
|
||||
fun Context.getNotificationPermissions(): Array<String> {
|
||||
val perms = mutableListOf<String>()
|
||||
if (android.os.Build.VERSION.SDK_INT >= 33)
|
||||
if (android.os.Build.VERSION.SDK_INT >= 33) {
|
||||
perms.add(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
|
||||
return getMissingPermissions(perms)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ open class ServiceClient<T : IInterface>(private val stubFactory: (IBinder) -> T
|
|||
|
||||
var serviceP: T? = null
|
||||
|
||||
/// A getter that returns the bound service or throws if not bound
|
||||
// A getter that returns the bound service or throws if not bound
|
||||
val service: T
|
||||
get() {
|
||||
waitConnect() // Wait for at least the initial connection to happen
|
||||
|
@ -40,11 +40,13 @@ open class ServiceClient<T : IInterface>(private val stubFactory: (IBinder) -> T
|
|||
fun waitConnect() {
|
||||
// Wait until this service is connected
|
||||
lock.withLock {
|
||||
if (context == null)
|
||||
if (context == null) {
|
||||
throw Exception("Haven't called connect")
|
||||
}
|
||||
|
||||
if (serviceP == null)
|
||||
if (serviceP == null) {
|
||||
condition.await()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,8 +73,7 @@ open class ServiceClient<T : IInterface>(private val stubFactory: (IBinder) -> T
|
|||
isClosed = true
|
||||
try {
|
||||
context?.unbindService(connection)
|
||||
}
|
||||
catch(ex: IllegalArgumentException) {
|
||||
} catch (ex: IllegalArgumentException) {
|
||||
// Autobugs show this can generate an illegal arg exception for "service not registered" during reinstall?
|
||||
warn("Ignoring error in ServiceClient.close, probably harmless")
|
||||
}
|
||||
|
@ -80,11 +81,11 @@ open class ServiceClient<T : IInterface>(private val stubFactory: (IBinder) -> T
|
|||
context = null
|
||||
}
|
||||
|
||||
/// Called when we become connected
|
||||
// Called when we become connected
|
||||
open fun onConnected(service: T) {
|
||||
}
|
||||
|
||||
/// called on loss of connection
|
||||
// called on loss of connection
|
||||
open fun onDisconnected() {
|
||||
}
|
||||
|
||||
|
@ -111,4 +112,4 @@ open class ServiceClient<T : IInterface>(private val stubFactory: (IBinder) -> T
|
|||
onDisconnected()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.geeksville.mesh.concurrent
|
|||
|
||||
import com.geeksville.mesh.android.Logging
|
||||
|
||||
|
||||
/**
|
||||
* A deferred execution object (with various possible implementations)
|
||||
*/
|
||||
|
@ -52,15 +51,17 @@ class SyncContinuation<T> : Continuation<T> {
|
|||
while (result == null) {
|
||||
mbox.wait(timeoutMsecs)
|
||||
|
||||
if (timeoutMsecs > 0 && ((System.currentTimeMillis() - startT) >= timeoutMsecs))
|
||||
if (timeoutMsecs > 0 && ((System.currentTimeMillis() - startT) >= timeoutMsecs)) {
|
||||
throw Exception("SyncContinuation timeout")
|
||||
}
|
||||
}
|
||||
|
||||
val r = result
|
||||
if (r != null)
|
||||
if (r != null) {
|
||||
return r.getOrThrow()
|
||||
else
|
||||
} else {
|
||||
throw Exception("This shouldn't happen")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,15 +29,15 @@ import com.geeksville.mesh.database.entity.QuickChatAction
|
|||
QuickChatAction::class
|
||||
],
|
||||
autoMigrations = [
|
||||
AutoMigration (from = 3, to = 4),
|
||||
AutoMigration (from = 4, to = 5),
|
||||
AutoMigration (from = 5, to = 6),
|
||||
AutoMigration (from = 6, to = 7),
|
||||
AutoMigration (from = 7, to = 8),
|
||||
AutoMigration (from = 8, to = 9),
|
||||
AutoMigration (from = 9, to = 10),
|
||||
AutoMigration (from = 10, to = 11),
|
||||
AutoMigration (from = 11, to = 12),
|
||||
AutoMigration(from = 3, to = 4),
|
||||
AutoMigration(from = 4, to = 5),
|
||||
AutoMigration(from = 5, to = 6),
|
||||
AutoMigration(from = 6, to = 7),
|
||||
AutoMigration(from = 7, to = 8),
|
||||
AutoMigration(from = 8, to = 9),
|
||||
AutoMigration(from = 9, to = 10),
|
||||
AutoMigration(from = 10, to = 11),
|
||||
AutoMigration(from = 11, to = 12),
|
||||
AutoMigration(from = 12, to = 13, spec = AutoMigration12to13::class),
|
||||
],
|
||||
version = 13,
|
||||
|
|
|
@ -29,5 +29,4 @@ interface MeshLogDao {
|
|||
|
||||
@Query("DELETE FROM log")
|
||||
fun deleteAll()
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ interface PacketDao {
|
|||
fun getContactSettings(): Flow<Map<@MapColumn(columnName = "contact_key") String, ContactSettings>>
|
||||
|
||||
@Query("SELECT * FROM contact_settings WHERE contact_key = :contact")
|
||||
suspend fun getContactSettings(contact:String): ContactSettings?
|
||||
suspend fun getContactSettings(contact: String): ContactSettings?
|
||||
|
||||
@Upsert
|
||||
fun upsertContactSettings(contacts: List<ContactSettings>)
|
||||
|
|
|
@ -107,9 +107,9 @@ data class NodeEntity(
|
|||
val validPosition: MeshProtos.Position? get() = position.takeIf { hasValidPosition() }
|
||||
|
||||
// @return distance in meters to some other node (or null if unknown)
|
||||
fun distance(o: NodeEntity): Int? {
|
||||
return if (validPosition == null || o.validPosition == null) null
|
||||
else latLongToMeter(latitude, longitude, o.latitude, o.longitude).toInt()
|
||||
fun distance(o: NodeEntity): Int? = when {
|
||||
validPosition == null || o.validPosition == null -> null
|
||||
else -> latLongToMeter(latitude, longitude, o.latitude, o.longitude).toInt()
|
||||
}
|
||||
|
||||
// @return a nice human readable string for the distance, or null for unknown
|
||||
|
@ -119,9 +119,9 @@ data class NodeEntity(
|
|||
}
|
||||
|
||||
// @return bearing to the other position in degrees
|
||||
fun bearing(o: NodeEntity?): Int? {
|
||||
return if (validPosition == null || o?.validPosition == null) null
|
||||
else bearing(latitude, longitude, o.latitude, o.longitude).toInt()
|
||||
fun bearing(o: NodeEntity?): Int? = when {
|
||||
validPosition == null || o?.validPosition == null -> null
|
||||
else -> bearing(latitude, longitude, o.latitude, o.longitude).toInt()
|
||||
}
|
||||
|
||||
fun gpsString(gpsFormat: Int): String = when (gpsFormat) {
|
||||
|
@ -140,7 +140,9 @@ data class NodeEntity(
|
|||
} else {
|
||||
"%.1f°C".format(temperature)
|
||||
}
|
||||
} else null
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val humidity = if (relativeHumidity != 0f) "%.0f%%".format(relativeHumidity) else null
|
||||
val pressure = if (barometricPressure != 0f) "%.1fhPa".format(barometricPressure) else null
|
||||
val gas = if (gasResistance != 0f) "%.0fMΩ".format(gasResistance) else null
|
||||
|
@ -188,7 +190,7 @@ data class NodeEntity(
|
|||
}
|
||||
|
||||
companion object {
|
||||
/// Convert to a double representation of degrees
|
||||
// Convert to a double representation of degrees
|
||||
fun degD(i: Int) = i * 1e-7
|
||||
fun degI(d: Double) = (d * 1e7).toInt()
|
||||
|
||||
|
|
|
@ -7,12 +7,13 @@ import androidx.room.PrimaryKey
|
|||
@Entity(tableName = "quick_chat")
|
||||
data class QuickChatAction(
|
||||
@PrimaryKey(autoGenerate = true) val uuid: Long,
|
||||
@ColumnInfo(name="name") val name: String,
|
||||
@ColumnInfo(name="message") val message: String,
|
||||
@ColumnInfo(name="mode") val mode: Mode,
|
||||
@ColumnInfo(name="position") val position: Int) {
|
||||
@ColumnInfo(name = "name") val name: String,
|
||||
@ColumnInfo(name = "message") val message: String,
|
||||
@ColumnInfo(name = "mode") val mode: Mode,
|
||||
@ColumnInfo(name = "position") val position: Int
|
||||
) {
|
||||
enum class Mode {
|
||||
Append,
|
||||
Instant,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ data class Channel(
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the name of our channel as a human readable string. If empty string, assume "Default" per mesh.proto spec
|
||||
// Return the name of our channel as a human readable string. If empty string, assume "Default" per mesh.proto spec
|
||||
val name: String
|
||||
get() = settings.name.ifEmpty {
|
||||
// We have a new style 'empty' channel name. Use the same logic from the device to convert that to a human readable name
|
||||
|
@ -66,15 +66,15 @@ data class Channel(
|
|||
}
|
||||
|
||||
val psk: ByteString
|
||||
get() = if (settings.psk.size() != 1)
|
||||
get() = if (settings.psk.size() != 1) {
|
||||
settings.psk // A standard PSK
|
||||
else {
|
||||
} else {
|
||||
// One of our special 1 byte PSKs, see mesh.proto for docs.
|
||||
val pskIndex = settings.psk.byteAt(0).toInt()
|
||||
|
||||
if (pskIndex == 0)
|
||||
if (pskIndex == 0) {
|
||||
cleartextPSK
|
||||
else {
|
||||
} else {
|
||||
// Treat an index of 1 as the old channelDefaultKey and work up from there
|
||||
val bytes = channelDefaultKey.clone()
|
||||
bytes[bytes.size - 1] = (0xff and (bytes[bytes.size - 1] + pskIndex - 1)).toByte()
|
||||
|
|
|
@ -40,8 +40,9 @@ private fun LoRaConfig.bandwidth() = if (usePreset) {
|
|||
|
||||
val LoRaConfig.numChannels: Int get() {
|
||||
for (option in RegionInfo.entries) {
|
||||
if (option.regionCode == region)
|
||||
if (option.regionCode == region) {
|
||||
return ((option.freqEnd - option.freqStart) / bandwidth()).toInt()
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
@ -55,8 +56,9 @@ internal fun LoRaConfig.channelNum(primaryName: String): Int = when {
|
|||
internal fun LoRaConfig.radioFreq(channelNum: Int): Float {
|
||||
if (overrideFrequency != 0f) return overrideFrequency + frequencyOffset
|
||||
for (option in RegionInfo.entries) {
|
||||
if (option.regionCode == region)
|
||||
if (option.regionCode == region) {
|
||||
return (option.freqStart + bandwidth() / 2) + (channelNum - 1) * bandwidth()
|
||||
}
|
||||
}
|
||||
return 0f
|
||||
}
|
||||
|
@ -103,5 +105,4 @@ enum class ChannelOption(
|
|||
LONG_MODERATE(ModemPreset.LONG_MODERATE, R.string.modem_config_mod_long, .125f),
|
||||
LONG_SLOW(ModemPreset.LONG_SLOW, R.string.modem_config_slow_long, .125f),
|
||||
VERY_LONG_SLOW(ModemPreset.VERY_LONG_SLOW, R.string.modem_config_very_long, .0625f),
|
||||
;
|
||||
}
|
||||
|
|
|
@ -469,8 +469,11 @@ class RadioConfigViewModel @Inject constructor(
|
|||
setResponseStateError(app.getString(parsed.errorReason.stringRes))
|
||||
} else if (packet.from == destNum && route.isEmpty()) {
|
||||
requestIds.update { it.apply { remove(data.requestId) } }
|
||||
if (requestIds.value.isEmpty()) setResponseStateSuccess()
|
||||
else incrementCompleted()
|
||||
if (requestIds.value.isEmpty()) {
|
||||
setResponseStateSuccess()
|
||||
} else {
|
||||
incrementCompleted()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data?.portnumValue == Portnums.PortNum.ADMIN_APP_VALUE) {
|
||||
|
|
|
@ -58,10 +58,10 @@ import java.util.concurrent.TimeUnit
|
|||
import javax.inject.Inject
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
// / Given a human name, strip out the first letter of the first three words and return that as the initials for
|
||||
// / that user. If the original name is only one word, strip vowels from the original name and if the result is
|
||||
// / 3 or more characters, use the first three characters. If not, just take the first 3 characters of the
|
||||
// / original name.
|
||||
// Given a human name, strip out the first letter of the first three words and return that as the initials for
|
||||
// that user. If the original name is only one word, strip vowels from the original name and if the result is
|
||||
// 3 or more characters, use the first three characters. If not, just take the first 3 characters of the
|
||||
// original name.
|
||||
fun getInitials(nameIn: String): String {
|
||||
val nchars = 4
|
||||
val minchars = 2
|
||||
|
@ -70,10 +70,11 @@ fun getInitials(nameIn: String): String {
|
|||
|
||||
val initials = when (words.size) {
|
||||
in 0 until minchars -> {
|
||||
val nm = if (name.isNotEmpty())
|
||||
val nm = if (name.isNotEmpty()) {
|
||||
name.first() + name.drop(1).filterNot { c -> c.lowercase() in "aeiou" }
|
||||
else
|
||||
} else {
|
||||
""
|
||||
}
|
||||
if (nm.length >= nchars) nm else name
|
||||
}
|
||||
else -> words.map { it.first() }.joinToString("")
|
||||
|
@ -414,7 +415,7 @@ class UIViewModel @Inject constructor(
|
|||
fun requestUserInfo(destNum: Int) {
|
||||
info("Requesting UserInfo for '$destNum'")
|
||||
try {
|
||||
meshService?.requestUserInfo( destNum )
|
||||
meshService?.requestUserInfo(destNum)
|
||||
} catch (ex: RemoteException) {
|
||||
errormsg("Request NodeInfo error: ${ex.message}")
|
||||
}
|
||||
|
@ -545,7 +546,7 @@ class UIViewModel @Inject constructor(
|
|||
fun setChannels(channelSet: AppOnlyProtos.ChannelSet, overwrite: Boolean = true) = viewModelScope.launch {
|
||||
val newRadioSettings: List<ChannelSettings> = if (overwrite) {
|
||||
channelSet.settingsList
|
||||
} else {
|
||||
} else {
|
||||
// To guarantee consistent ordering, using a LinkedHashSet which iterates through it's
|
||||
// entries according to the order an item was *first* inserted.
|
||||
// https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-linked-hash-set/
|
||||
|
|
|
@ -43,7 +43,6 @@ class MarkerWithLabel(mapView: MapView?, label: String, emoji: String? = null) :
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private var onLongClickListener: (() -> Boolean)? = null
|
||||
|
||||
fun setOnLongClickListener(listener: () -> Boolean) {
|
||||
|
@ -93,7 +92,7 @@ class MarkerWithLabel(mapView: MapView?, label: String, emoji: String? = null) :
|
|||
val bgRect = getTextBackgroundSize(mLabel, (p.x - 0F), (p.y - LABEL_Y_OFFSET))
|
||||
bgRect.inset(-8F, -2F)
|
||||
|
||||
if(mLabel.isNotEmpty()) {
|
||||
if (mLabel.isNotEmpty()) {
|
||||
c.drawRoundRect(bgRect, LABEL_CORNER_RADIUS, LABEL_CORNER_RADIUS, bgPaint)
|
||||
c.drawText(mLabel, (p.x - 0F), (p.y - LABEL_Y_OFFSET), textPaint)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import javax.inject.Inject
|
|||
class BluetoothInterfaceSpec @Inject constructor(
|
||||
private val factory: BluetoothInterfaceFactory,
|
||||
private val bluetoothRepository: BluetoothRepository,
|
||||
): InterfaceSpec<BluetoothInterface>, Logging {
|
||||
) : InterfaceSpec<BluetoothInterface>, Logging {
|
||||
override fun createInterface(rest: String): BluetoothInterface {
|
||||
return factory.create(rest)
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ class BluetoothInterfaceSpec @Inject constructor(
|
|||
return if (!allPaired.contains(rest)) {
|
||||
warn("Ignoring stale bond to ${rest.anonymize}")
|
||||
false
|
||||
} else
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import javax.inject.Provider
|
|||
class InterfaceFactory @Inject constructor(
|
||||
private val nopInterfaceFactory: NopInterfaceFactory,
|
||||
private val specMap: Map<InterfaceId, @JvmSuppressWildcards Provider<InterfaceSpec<*>>>
|
||||
) {
|
||||
) {
|
||||
internal val nopInterface by lazy {
|
||||
nopInterfaceFactory.create("")
|
||||
}
|
||||
|
@ -38,4 +38,4 @@ class InterfaceFactory @Inject constructor(
|
|||
val rest = address.substring(1)
|
||||
return Pair(c, rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,6 @@ package com.geeksville.mesh.repository.radio
|
|||
* This is primarily used in conjunction with Dagger assisted injection for each backend
|
||||
* interface type.
|
||||
*/
|
||||
interface InterfaceFactorySpi<T: IRadioInterface> {
|
||||
interface InterfaceFactorySpi<T : IRadioInterface> {
|
||||
fun create(rest: String): T
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import javax.inject.Inject
|
|||
*/
|
||||
class MockInterfaceSpec @Inject constructor(
|
||||
private val factory: MockInterfaceFactory
|
||||
): InterfaceSpec<MockInterface> {
|
||||
) : InterfaceSpec<MockInterface> {
|
||||
override fun createInterface(rest: String): MockInterface {
|
||||
return factory.create(rest)
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import javax.inject.Inject
|
|||
*/
|
||||
class NopInterfaceSpec @Inject constructor(
|
||||
private val factory: NopInterfaceFactory
|
||||
): InterfaceSpec<NopInterface> {
|
||||
) : InterfaceSpec<NopInterface> {
|
||||
override fun createInterface(rest: String): NopInterface {
|
||||
return factory.create(rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import kotlinx.coroutines.launch
|
|||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
/**
|
||||
* Handles the bluetooth link with a mesh radio device. Does not cache any device state,
|
||||
* just does bluetooth comms etc...
|
||||
|
@ -79,7 +78,7 @@ class RadioInterfaceService @Inject constructor(
|
|||
*/
|
||||
private var isStarted = false
|
||||
|
||||
/// true if our interface is currently connected to a device
|
||||
// true if our interface is currently connected to a device
|
||||
private var isConnected = false
|
||||
|
||||
private fun initStateListeners() {
|
||||
|
@ -156,7 +155,7 @@ class RadioInterfaceService @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
/// Send a packet/command out the radio link, this routine can block if it needs to
|
||||
// Send a packet/command out the radio link, this routine can block if it needs to
|
||||
private fun handleSendToRadio(p: ByteArray) {
|
||||
radioIf.handleSendToRadio(p)
|
||||
}
|
||||
|
@ -191,20 +190,22 @@ class RadioInterfaceService @Inject constructor(
|
|||
|
||||
/** Start our configured interface (if it isn't already running) */
|
||||
private fun startInterface() {
|
||||
if (radioIf !is NopInterface)
|
||||
if (radioIf !is NopInterface) {
|
||||
warn("Can't start interface - $radioIf is already running")
|
||||
else {
|
||||
} else {
|
||||
val address = getBondedDeviceAddress()
|
||||
if (address == null)
|
||||
if (address == null) {
|
||||
warn("No bonded mesh radio, can't start interface")
|
||||
else {
|
||||
} else {
|
||||
info("Starting radio ${address.anonymize}")
|
||||
isStarted = true
|
||||
|
||||
if (logSends)
|
||||
if (logSends) {
|
||||
sentPacketsLog = BinaryLogFile(context, "sent_log.pb")
|
||||
if (logReceives)
|
||||
}
|
||||
if (logReceives) {
|
||||
receivedPacketsLog = BinaryLogFile(context, "receive_log.pb")
|
||||
}
|
||||
|
||||
radioIf = interfaceFactory.createInterface(address)
|
||||
}
|
||||
|
@ -222,17 +223,19 @@ class RadioInterfaceService @Inject constructor(
|
|||
serviceScope.cancel("stopping interface")
|
||||
serviceScope = CoroutineScope(Dispatchers.IO + Job())
|
||||
|
||||
if (logSends)
|
||||
if (logSends) {
|
||||
sentPacketsLog.close()
|
||||
if (logReceives)
|
||||
}
|
||||
if (logReceives) {
|
||||
receivedPacketsLog.close()
|
||||
}
|
||||
|
||||
// Don't broadcast disconnects if we were just using the nop device
|
||||
if (r !is NopInterface)
|
||||
if (r !is NopInterface) {
|
||||
onDisconnect(isPermanent = true) // Tell any clients we are now offline
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change to a new device
|
||||
*
|
||||
|
@ -258,10 +261,11 @@ class RadioInterfaceService @Inject constructor(
|
|||
debug("Setting bonded device to ${address.anonymize}")
|
||||
|
||||
prefs.edit {
|
||||
if (address == null)
|
||||
if (address == null) {
|
||||
this.remove(DEVADDR_KEY)
|
||||
else
|
||||
} else {
|
||||
putString(DEVADDR_KEY, address)
|
||||
}
|
||||
}
|
||||
|
||||
// Force the service to reconnect
|
||||
|
|
|
@ -12,7 +12,7 @@ class SerialInterfaceSpec @Inject constructor(
|
|||
private val factory: SerialInterfaceFactory,
|
||||
private val usbManager: dagger.Lazy<UsbManager>,
|
||||
private val usbRepository: UsbRepository,
|
||||
): InterfaceSpec<SerialInterface> {
|
||||
) : InterfaceSpec<SerialInterface> {
|
||||
override fun createInterface(rest: String): SerialInterface {
|
||||
return factory.create(rest)
|
||||
}
|
||||
|
@ -37,4 +37,4 @@ class SerialInterfaceSpec @Inject constructor(
|
|||
deviceMap.map { (_, driver) -> driver }.firstOrNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.geeksville.mesh.repository.radio
|
|||
|
||||
import com.geeksville.mesh.android.Logging
|
||||
|
||||
|
||||
/**
|
||||
* An interface that assumes we are talking to a meshtastic device over some sort of stream connection (serial or TCP probably)
|
||||
*/
|
||||
|
@ -49,7 +48,7 @@ abstract class StreamInterface(protected val service: RadioInterfaceService) :
|
|||
|
||||
abstract fun sendBytes(p: ByteArray)
|
||||
|
||||
/// If subclasses need to flash at the end of a packet they can implement
|
||||
// If subclasses need to flash at the end of a packet they can implement
|
||||
open fun flushBytes() {}
|
||||
|
||||
override fun handleSendToRadio(p: ByteArray) {
|
||||
|
@ -66,7 +65,6 @@ abstract class StreamInterface(protected val service: RadioInterfaceService) :
|
|||
flushBytes()
|
||||
}
|
||||
|
||||
|
||||
/** Print device serial debug output somewhere */
|
||||
private fun debugOut(b: Byte) {
|
||||
when (val c = b.toChar()) {
|
||||
|
@ -92,7 +90,7 @@ abstract class StreamInterface(protected val service: RadioInterfaceService) :
|
|||
nextPtr = 0
|
||||
}
|
||||
|
||||
/// Deliver our current packet and restart our reader
|
||||
// Deliver our current packet and restart our reader
|
||||
fun deliverPacket() {
|
||||
val buf = rxPacket.copyOf(packetLen)
|
||||
service.handleFromRadio(buf)
|
||||
|
@ -107,8 +105,9 @@ abstract class StreamInterface(protected val service: RadioInterfaceService) :
|
|||
nextPtr = 0 // Restart from scratch
|
||||
}
|
||||
1 -> // Looking for START2
|
||||
if (c != START2)
|
||||
if (c != START2) {
|
||||
lostSync() // Restart from scratch
|
||||
}
|
||||
2 -> // Looking for MSB of our 16 bit length
|
||||
msb = c.toInt() and 0xff
|
||||
3 -> { // Looking for LSB of our 16 bit length
|
||||
|
@ -116,10 +115,11 @@ abstract class StreamInterface(protected val service: RadioInterfaceService) :
|
|||
|
||||
// We've read our header, do one big read for the packet itself
|
||||
packetLen = (msb shl 8) or lsb
|
||||
if (packetLen > MAX_TO_FROM_RADIO_SIZE)
|
||||
lostSync() // If packet len is too long, the bytes must have been corrupted, start looking for START1 again
|
||||
else if (packetLen == 0)
|
||||
if (packetLen > MAX_TO_FROM_RADIO_SIZE) {
|
||||
lostSync() // If packet len is too long, the bytes must have been corrupted, start looking for START1 again
|
||||
} else if (packetLen == 0) {
|
||||
deliverPacket() // zero length packets are valid and should be delivered immediately (because there won't be a next byte of payload)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// We are looking at the packet bytes now
|
||||
|
@ -133,4 +133,4 @@ abstract class StreamInterface(protected val service: RadioInterfaceService) :
|
|||
}
|
||||
ptr = nextPtr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import javax.inject.Inject
|
|||
*/
|
||||
class TCPInterfaceSpec @Inject constructor(
|
||||
private val factory: TCPInterfaceFactory
|
||||
): InterfaceSpec<TCPInterface> {
|
||||
) : InterfaceSpec<TCPInterface> {
|
||||
override fun createInterface(rest: String): TCPInterface {
|
||||
return factory.create(rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ internal class SerialConnectionImpl(
|
|||
private val device: UsbSerialDriver,
|
||||
private val listener: SerialConnectionListener
|
||||
) : SerialConnection, Logging {
|
||||
private val port = device.ports[0] // Most devices have just one port (port 0)
|
||||
private val port = device.ports[0] // Most devices have just one port (port 0)
|
||||
private val closedLatch = CountDownLatch(1)
|
||||
private val closed = AtomicBoolean(false)
|
||||
private val ioRef = AtomicReference<SerialInputOutputManager>()
|
||||
|
@ -80,7 +80,7 @@ internal class SerialConnectionImpl(
|
|||
listener.onDisconnected(e)
|
||||
}
|
||||
}).apply {
|
||||
readTimeout = 200 // To save battery we only timeout ever so often
|
||||
readTimeout = 200 // To save battery we only timeout ever so often
|
||||
ioRef.set(this)
|
||||
}
|
||||
|
||||
|
@ -92,4 +92,4 @@ internal class SerialConnectionImpl(
|
|||
|
||||
listener.onConnected()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ class UsbRepository @Inject constructor(
|
|||
|
||||
@Suppress("unused") // Retained as public API
|
||||
val serialDevicesWithDrivers = _serialDevices
|
||||
.mapLatest { serialDevices ->
|
||||
.mapLatest { serialDevices ->
|
||||
val serialProber = usbSerialProberLazy.get()
|
||||
buildMap {
|
||||
serialDevices.forEach { (k, v) ->
|
||||
|
@ -72,7 +72,7 @@ class UsbRepository @Inject constructor(
|
|||
* Creates a USB serial connection to the specified USB device. State changes and data arrival
|
||||
* result in async callbacks on the supplied listener.
|
||||
*/
|
||||
fun createSerialConnection(device: UsbSerialDriver, listener: SerialConnectionListener) : SerialConnection {
|
||||
fun createSerialConnection(device: UsbSerialDriver, listener: SerialConnectionListener): SerialConnection {
|
||||
return SerialConnectionImpl(usbManagerLazy, device, listener)
|
||||
}
|
||||
|
||||
|
@ -88,4 +88,4 @@ class UsbRepository @Inject constructor(
|
|||
private suspend fun refreshStateInternal() = withContext(dispatchers.default) {
|
||||
_serialDevices.emit(usbManagerLazy.get()?.deviceList ?: emptyMap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,11 +88,11 @@ class MeshService : Service(), Logging {
|
|||
|
||||
companion object : Logging {
|
||||
|
||||
/// Intents broadcast by MeshService
|
||||
// Intents broadcast by MeshService
|
||||
|
||||
private fun actionReceived(portNum: String) = "$prefix.RECEIVED.$portNum"
|
||||
|
||||
/// generate a RECEIVED action filter string that includes either the portnumber as an int, or preferably a symbolic name from portnums.proto
|
||||
// generate a RECEIVED action filter string that includes either the portnumber as an int, or preferably a symbolic name from portnums.proto
|
||||
fun actionReceived(portNum: Int): String {
|
||||
val portType = Portnums.PortNum.forNumber(portNum)
|
||||
val portStr = portType?.toString() ?: portNum.toString()
|
||||
|
@ -141,7 +141,7 @@ class MeshService : Service(), Logging {
|
|||
private var previousSummary: String? = null
|
||||
private var previousStats: LocalStats? = null
|
||||
|
||||
/// A mapping of receiver class name to package name - used for explicit broadcasts
|
||||
// A mapping of receiver class name to package name - used for explicit broadcasts
|
||||
private val clientPackages = mutableMapOf<String, String>()
|
||||
private val serviceNotifications = MeshServiceNotifications(this)
|
||||
private val serviceBroadcasts = MeshServiceBroadcasts(this, clientPackages) {
|
||||
|
@ -337,9 +337,9 @@ class MeshService : Service(), Logging {
|
|||
serviceJob.cancel()
|
||||
}
|
||||
|
||||
///
|
||||
/// BEGINNING OF MODEL - FIXME, move elsewhere
|
||||
///
|
||||
//
|
||||
// BEGINNING OF MODEL - FIXME, move elsewhere
|
||||
//
|
||||
|
||||
private fun loadSettings() {
|
||||
discardNodeDB() // Get rid of any old state
|
||||
|
@ -368,7 +368,7 @@ class MeshService : Service(), Logging {
|
|||
private var moduleConfig: LocalModuleConfig = LocalModuleConfig.getDefaultInstance()
|
||||
private var channelSet: AppOnlyProtos.ChannelSet = AppOnlyProtos.ChannelSet.getDefaultInstance()
|
||||
|
||||
/// True after we've done our initial node db init
|
||||
// True after we've done our initial node db init
|
||||
@Volatile
|
||||
private var haveNodeDB = false
|
||||
|
||||
|
@ -379,15 +379,15 @@ class MeshService : Service(), Logging {
|
|||
// NOTE: some NodeInfos might be in only nodeDBbyNodeNum (because we don't yet know an ID).
|
||||
private val nodeDBbyID get() = nodeDBbyNodeNum.mapKeys { it.value.user.id }
|
||||
|
||||
///
|
||||
/// END OF MODEL
|
||||
///
|
||||
//
|
||||
// END OF MODEL
|
||||
//
|
||||
|
||||
private val deviceVersion get() = DeviceVersion(myNodeInfo?.firmwareVersion ?: "")
|
||||
private val appVersion get() = BuildConfig.VERSION_CODE
|
||||
private val minAppVersion get() = myNodeInfo?.minAppVersion ?: 0
|
||||
|
||||
/// Map a nodenum to a node, or throw an exception if not found
|
||||
// Map a nodenum to a node, or throw an exception if not found
|
||||
private fun toNodeInfo(n: Int) = nodeDBbyNodeNum[n] ?: throw NodeNumNotFoundException(n)
|
||||
|
||||
/** Map a nodeNum to the nodeId string
|
||||
|
@ -395,8 +395,11 @@ class MeshService : Service(), Logging {
|
|||
but some nodes might not have a user record at all (because not yet received), in that case, we return
|
||||
a hex version of the ID just based on the number */
|
||||
private fun toNodeID(n: Int): String =
|
||||
if (n == DataPacket.NODENUM_BROADCAST) DataPacket.ID_BROADCAST
|
||||
else nodeDBbyNodeNum[n]?.user?.id ?: DataPacket.nodeNumToDefaultId(n)
|
||||
if (n == DataPacket.NODENUM_BROADCAST) {
|
||||
DataPacket.ID_BROADCAST
|
||||
} else {
|
||||
nodeDBbyNodeNum[n]?.user?.id ?: DataPacket.nodeNumToDefaultId(n)
|
||||
}
|
||||
|
||||
// given a nodeNum, return a db entry - creating if necessary
|
||||
private fun getOrCreateNodeInfo(n: Int) = nodeDBbyNodeNum.getOrPut(n) {
|
||||
|
@ -418,8 +421,8 @@ class MeshService : Service(), Logging {
|
|||
private val hexIdRegex = """\!([0-9A-Fa-f]+)""".toRegex()
|
||||
private val rangeTestRegex = Regex("seq (\\d{1,10})")
|
||||
|
||||
/// Map a userid to a node/ node num, or throw an exception if not found
|
||||
/// We prefer to find nodes based on their assigned IDs, but if no ID has been assigned to a node, we can also find it based on node number
|
||||
// Map a userid to a node/ node num, or throw an exception if not found
|
||||
// We prefer to find nodes based on their assigned IDs, but if no ID has been assigned to a node, we can also find it based on node number
|
||||
private fun toNodeInfo(id: String): NodeEntity {
|
||||
// If this is a valid hexaddr will be !null
|
||||
val hexStr = hexIdRegex.matchEntire(id)?.groups?.get(1)?.value
|
||||
|
@ -454,7 +457,7 @@ class MeshService : Service(), Logging {
|
|||
else -> toNodeInfo(id).num
|
||||
}
|
||||
|
||||
/// A helper function that makes it easy to update node info objects
|
||||
// A helper function that makes it easy to update node info objects
|
||||
private inline fun updateNodeInfo(
|
||||
nodeNum: Int,
|
||||
withBroadcast: Boolean = true,
|
||||
|
@ -463,25 +466,26 @@ class MeshService : Service(), Logging {
|
|||
val info = getOrCreateNodeInfo(nodeNum)
|
||||
updateFn(info)
|
||||
|
||||
if (info.user.id.isNotEmpty()) {
|
||||
if (haveNodeDB) serviceScope.handledLaunch {
|
||||
if (info.user.id.isNotEmpty() && haveNodeDB) {
|
||||
serviceScope.handledLaunch {
|
||||
radioConfigRepository.upsert(info)
|
||||
}
|
||||
}
|
||||
|
||||
if (withBroadcast)
|
||||
if (withBroadcast) {
|
||||
serviceBroadcasts.broadcastNodeChange(info.toNodeInfo())
|
||||
}
|
||||
}
|
||||
|
||||
/// My node num
|
||||
// My node num
|
||||
private val myNodeNum
|
||||
get() = myNodeInfo?.myNodeNum
|
||||
?: throw RadioNotConnectedException("We don't yet have our myNodeInfo")
|
||||
|
||||
/// My node ID string
|
||||
// My node ID string
|
||||
private val myNodeID get() = toNodeID(myNodeNum)
|
||||
|
||||
/// Admin channel index
|
||||
// Admin channel index
|
||||
private val MeshPacket.Builder.adminChannelIndex: Int
|
||||
get() = when {
|
||||
myNodeNum == to -> 0
|
||||
|
@ -493,10 +497,11 @@ class MeshService : Service(), Logging {
|
|||
.coerceAtLeast(0)
|
||||
}
|
||||
|
||||
/// Generate a new mesh packet builder with our node as the sender, and the specified node num
|
||||
// Generate a new mesh packet builder with our node as the sender, and the specified node num
|
||||
private fun newMeshPacketTo(idNum: Int) = MeshPacket.newBuilder().apply {
|
||||
if (myNodeInfo == null)
|
||||
if (myNodeInfo == null) {
|
||||
throw RadioNotConnectedException()
|
||||
}
|
||||
|
||||
from = 0 // don't add myNodeNum
|
||||
|
||||
|
@ -540,7 +545,6 @@ class MeshService : Service(), Logging {
|
|||
return build()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to make it easy to build a subpacket in the proper protobufs
|
||||
*/
|
||||
|
@ -562,7 +566,7 @@ class MeshService : Service(), Logging {
|
|||
}.build().toByteString()
|
||||
}
|
||||
|
||||
/// Generate a DataPacket from a MeshPacket, or null if we didn't have enough data to do so
|
||||
// Generate a DataPacket from a MeshPacket, or null if we didn't have enough data to do so
|
||||
private fun toDataPacket(packet: MeshPacket): DataPacket? {
|
||||
return if (!packet.hasDecoded()) {
|
||||
// We never convert packets that are not DataPackets
|
||||
|
@ -631,7 +635,7 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
private fun handleReceivedData(packet: MeshPacket) {
|
||||
myNodeInfo?.let { myInfo ->
|
||||
val data = packet.decoded
|
||||
|
@ -650,7 +654,7 @@ class MeshService : Service(), Logging {
|
|||
|
||||
// if (p.hasUser()) handleReceivedUser(fromNum, p.user)
|
||||
|
||||
/// We tell other apps about most message types, but some may have sensitve data, so that is not shared'
|
||||
// We tell other apps about most message types, but some may have sensitive data, so that is not shared'
|
||||
var shouldBroadcast = !fromUs
|
||||
|
||||
when (data.portnumValue) {
|
||||
|
@ -747,8 +751,9 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
|
||||
// We always tell other apps when new data packets arrive
|
||||
if (shouldBroadcast)
|
||||
if (shouldBroadcast) {
|
||||
serviceBroadcasts.broadcastReceivedData(dataPacket)
|
||||
}
|
||||
|
||||
GeeksvilleApplication.analytics.track(
|
||||
"num_data_receive",
|
||||
|
@ -784,9 +789,7 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
}
|
||||
else ->
|
||||
warn("No special processing needed for ${a.payloadVariantCase}")
|
||||
|
||||
else -> warn("No special processing needed for ${a.payloadVariantCase}")
|
||||
}
|
||||
} else {
|
||||
debug("Admin: Received session_passkey from $fromNodeNum")
|
||||
|
@ -794,7 +797,7 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/// Update our DB of users based on someone sending out a User subpacket
|
||||
// Update our DB of users based on someone sending out a User subpacket
|
||||
private fun handleReceivedUser(fromNum: Int, p: MeshProtos.User, channel: Int = 0) {
|
||||
updateNodeInfo(fromNum) {
|
||||
val keyMatch = !it.hasPKC || it.user.publicKey == p.publicKey
|
||||
|
@ -829,20 +832,14 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private fun handleLocalStats(stats: TelemetryProtos.Telemetry) {
|
||||
localStatsTelemetry = stats
|
||||
maybeUpdateServiceStatusNotification()
|
||||
}
|
||||
|
||||
|
||||
/// Update our DB of users based on someone sending out a Telemetry subpacket
|
||||
// Update our DB of users based on someone sending out a Telemetry subpacket
|
||||
private fun handleReceivedTelemetry(
|
||||
fromNum: Int,
|
||||
t: TelemetryProtos.Telemetry,
|
||||
) {
|
||||
if (t.hasLocalStats()) {
|
||||
handleLocalStats(t)
|
||||
localStatsTelemetry = t
|
||||
maybeUpdateServiceStatusNotification()
|
||||
}
|
||||
updateNodeInfo(fromNum) {
|
||||
when {
|
||||
|
@ -903,7 +900,9 @@ class MeshService : Service(), Logging {
|
|||
private fun formatTraceroutePath(nodesList: List<Int>, snrList: List<Int>): String {
|
||||
// nodesList should include both origin and destination nodes
|
||||
// origin will not have an SNR value, but destination should
|
||||
val snrStr = if (snrList.size == nodesList.size - 1) snrList else {
|
||||
val snrStr = if (snrList.size == nodesList.size - 1) {
|
||||
snrList
|
||||
} else {
|
||||
// use unknown SNR for entire route if snrList has invalid size
|
||||
List(nodesList.size - 1) { -128 }
|
||||
}.map { snr ->
|
||||
|
@ -914,7 +913,7 @@ class MeshService : Service(), Logging {
|
|||
return nodesList.map { nodeId ->
|
||||
"■ ${getUserName(nodeId)}"
|
||||
}.flatMapIndexed { i, nodeStr ->
|
||||
if (i == 0) listOf(nodeStr) else listOf(snrStr[i-1], nodeStr)
|
||||
if (i == 0) listOf(nodeStr) else listOf(snrStr[i - 1], nodeStr)
|
||||
}.joinToString("\n")
|
||||
}
|
||||
|
||||
|
@ -945,15 +944,15 @@ class MeshService : Service(), Logging {
|
|||
// If apps try to send packets when our radio is sleeping, we queue them here instead
|
||||
private val offlineSentPackets = mutableListOf<DataPacket>()
|
||||
|
||||
/// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
private fun handleReceivedMeshPacket(packet: MeshPacket) {
|
||||
if (haveNodeDB) {
|
||||
processReceivedMeshPacket(packet)
|
||||
onNodeDBChanged()
|
||||
} else {
|
||||
warn("Ignoring early received packet: ${packet.toOneLineString()}")
|
||||
//earlyReceivedPackets.add(packet)
|
||||
//logAssert(earlyReceivedPackets.size < 128) // The max should normally be about 32, but if the device is messed up it might try to send forever
|
||||
// earlyReceivedPackets.add(packet)
|
||||
// logAssert(earlyReceivedPackets.size < 128) // The max should normally be about 32, but if the device is messed up it might try to send forever
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1072,13 +1071,13 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
private fun processReceivedMeshPacket(packet: MeshPacket) {
|
||||
val fromNum = packet.from
|
||||
|
||||
// FIXME, perhaps we could learn our node ID by looking at any to packets the radio
|
||||
// decided to pass through to us (except for broadcast packets)
|
||||
//val toNum = packet.to
|
||||
// val toNum = packet.to
|
||||
|
||||
// debug("Recieved: $packet")
|
||||
if (packet.hasDecoded()) {
|
||||
|
@ -1160,8 +1159,7 @@ class MeshService : Service(), Logging {
|
|||
|
||||
private fun currentSecond() = (System.currentTimeMillis() / 1000).toInt()
|
||||
|
||||
|
||||
/// If we just changed our nodedb, we might want to do somethings
|
||||
// If we just changed our nodedb, we might want to do somethings
|
||||
private fun onNodeDBChanged() {
|
||||
maybeUpdateServiceStatusNotification()
|
||||
}
|
||||
|
@ -1189,14 +1187,14 @@ class MeshService : Service(), Logging {
|
|||
|
||||
private var sleepTimeout: Job? = null
|
||||
|
||||
/// msecs since 1970 we started this connection
|
||||
// msecs since 1970 we started this connection
|
||||
private var connectTimeMsec = 0L
|
||||
|
||||
/// Called when we gain/lose connection to our radio
|
||||
// Called when we gain/lose connection to our radio
|
||||
private fun onConnectionChanged(c: ConnectionState) {
|
||||
debug("onConnectionChanged: $connectionState -> $c")
|
||||
|
||||
/// Perform all the steps needed once we start waiting for device sleep to complete
|
||||
// Perform all the steps needed once we start waiting for device sleep to complete
|
||||
fun startDeviceSleep() {
|
||||
stopPacketQueue()
|
||||
stopLocationRequests()
|
||||
|
@ -1355,13 +1353,13 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/// A provisional MyNodeInfo that we will install if all of our node config downloads go okay
|
||||
// A provisional MyNodeInfo that we will install if all of our node config downloads go okay
|
||||
private var newMyNodeInfo: MyNodeEntity? = null
|
||||
|
||||
/// provisional NodeInfos we will install if all goes well
|
||||
// provisional NodeInfos we will install if all goes well
|
||||
private val newNodes = mutableListOf<MeshProtos.NodeInfo>()
|
||||
|
||||
/// Used to make sure we never get foold by old BLE packets
|
||||
// Used to make sure we never get foold by old BLE packets
|
||||
private var configNonce = 1
|
||||
|
||||
private fun handleDeviceConfig(config: ConfigProtos.Config) {
|
||||
|
@ -1400,8 +1398,11 @@ class MeshService : Service(), Logging {
|
|||
Triple(res == 0, free == 0, meshPacketId)
|
||||
}
|
||||
if (success && isFull) return // Queue is full, wait for free != 0
|
||||
if (requestId != 0) queueResponse.remove(requestId)?.complete(success)
|
||||
else queueResponse.entries.lastOrNull { !it.value.isDone }?.value?.complete(success)
|
||||
if (requestId != 0) {
|
||||
queueResponse.remove(requestId)?.complete(success)
|
||||
} else {
|
||||
queueResponse.entries.lastOrNull { !it.value.isDone }?.value?.complete(success)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleChannel(ch: ChannelProtos.Channel) {
|
||||
|
@ -1484,9 +1485,9 @@ class MeshService : Service(), Logging {
|
|||
val mi = with(myInfo) {
|
||||
MyNodeEntity(
|
||||
myNodeNum = myNodeNum,
|
||||
model = rawDeviceMetadata?.hwModel?.let { hwModel ->
|
||||
if (hwModel == MeshProtos.HardwareModel.UNSET) null
|
||||
else hwModel.name.replace('_', '-').replace('p', '.').lowercase()
|
||||
model = when (val hwModel = rawDeviceMetadata?.hwModel) {
|
||||
null, MeshProtos.HardwareModel.UNSET -> null
|
||||
else -> hwModel.name.replace('_', '-').replace('p', '.').lowercase()
|
||||
},
|
||||
firmwareVersion = rawDeviceMetadata?.firmwareVersion,
|
||||
couldUpdate = false,
|
||||
|
@ -1506,7 +1507,7 @@ class MeshService : Service(), Logging {
|
|||
val myInfo = rawMyNodeInfo
|
||||
val mi = myNodeInfo
|
||||
if (myInfo != null && mi != null) {
|
||||
/// Track types of devices and firmware versions in use
|
||||
// Track types of devices and firmware versions in use
|
||||
GeeksvilleApplication.analytics.setUserInfo(
|
||||
DataPair("firmware", mi.firmwareVersion),
|
||||
DataPair("hw_model", mi.model),
|
||||
|
@ -1603,7 +1604,7 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
/// If we've received our initial config, our radio settings and all of our channels, send any queued packets and broadcast connected to clients
|
||||
// If we've received our initial config, our radio settings and all of our channels, send any queued packets and broadcast connected to clients
|
||||
private fun onHasSettings() {
|
||||
|
||||
processQueuedPackets() // send any packets that were queued up
|
||||
|
@ -1731,8 +1732,7 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Do not use directly, instead call generatePacketId()
|
||||
// Do not use directly, instead call generatePacketId()
|
||||
private var currentPacketId = Random(System.currentTimeMillis()).nextLong().absoluteValue
|
||||
|
||||
/**
|
||||
|
@ -1816,13 +1816,16 @@ class MeshService : Service(), Logging {
|
|||
|
||||
info("sendData dest=${p.to}, id=${p.id} <- ${p.bytes!!.size} bytes (connectionState=$connectionState)")
|
||||
|
||||
if (p.dataType == 0)
|
||||
if (p.dataType == 0) {
|
||||
throw Exception("Port numbers must be non-zero!") // we are now more strict
|
||||
}
|
||||
|
||||
if (p.bytes.size >= MeshProtos.Constants.DATA_PAYLOAD_LEN.number) {
|
||||
p.status = MessageStatus.ERROR
|
||||
throw RemoteException("Message too long")
|
||||
} else p.status = MessageStatus.QUEUED
|
||||
} else {
|
||||
p.status = MessageStatus.QUEUED
|
||||
}
|
||||
|
||||
if (connectionState == ConnectionState.CONNECTED) try {
|
||||
sendNow(p)
|
||||
|
@ -1974,7 +1977,7 @@ class MeshService : Service(), Logging {
|
|||
removeByNodenum = nodeNum
|
||||
})
|
||||
}
|
||||
override fun requestUserInfo( destNum: Int ) = toRemoteExceptions {
|
||||
override fun requestUserInfo(destNum: Int) = toRemoteExceptions {
|
||||
if (destNum != myNodeNum) {
|
||||
sendToRadio(newMeshPacketTo(destNum
|
||||
).buildMeshPacket(
|
||||
|
|
|
@ -223,7 +223,7 @@ fun ChannelScreen(
|
|||
.show()
|
||||
}
|
||||
|
||||
/// Send new channel settings to the device
|
||||
// Send new channel settings to the device
|
||||
fun installSettings(
|
||||
newChannelSet: ChannelSet
|
||||
) {
|
||||
|
@ -420,8 +420,11 @@ fun ChannelScreen(
|
|||
!isUrlEqual -> stringResource(R.string.send)
|
||||
else -> "Copy"
|
||||
},
|
||||
tint = if (isError) MaterialTheme.colors.error
|
||||
else LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
|
||||
tint = if (isError) {
|
||||
MaterialTheme.colors.error
|
||||
} else {
|
||||
LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -60,7 +60,8 @@ class DebugFragment : Fragment() {
|
|||
private val model: DebugViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentDebugBinding.inflate(inflater, container, false)
|
||||
|
|
|
@ -170,7 +170,6 @@ enum class AdminRoute(@StringRes val title: Int) {
|
|||
SHUTDOWN(R.string.shutdown),
|
||||
FACTORY_RESET(R.string.factory_reset),
|
||||
NODEDB_RESET(R.string.nodedb_reset),
|
||||
;
|
||||
}
|
||||
|
||||
// Config (configType = AdminProtos.AdminMessage.ConfigType)
|
||||
|
@ -185,7 +184,6 @@ enum class ConfigRoute(val title: String, val configType: Int = 0) {
|
|||
LORA("LoRa", 5),
|
||||
BLUETOOTH("Bluetooth", 6),
|
||||
SECURITY("Security", configType = 7),
|
||||
;
|
||||
}
|
||||
|
||||
// ModuleConfig (configType = AdminProtos.AdminMessage.ModuleConfigType)
|
||||
|
@ -203,7 +201,6 @@ enum class ModuleRoute(val title: String, val configType: Int = 0) {
|
|||
AMBIENT_LIGHTING("Ambient Lighting", 10),
|
||||
DETECTION_SENSOR("Detection Sensor", 11),
|
||||
PAXCOUNTER("Paxcounter", 12),
|
||||
;
|
||||
}
|
||||
|
||||
private fun getName(route: Any): String = when (route) {
|
||||
|
@ -655,8 +652,11 @@ private fun NavCard(
|
|||
enabled: Boolean,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val color = if (enabled) MaterialTheme.colors.onSurface
|
||||
else MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled)
|
||||
val color = if (enabled) {
|
||||
MaterialTheme.colors.onSurface
|
||||
} else {
|
||||
MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled)
|
||||
}
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
|
|
|
@ -44,7 +44,7 @@ fun LinkedCoordinates(
|
|||
tag = "gps",
|
||||
// URI scheme is defined at:
|
||||
// https://developer.android.com/guide/components/intents-common#Maps
|
||||
annotation = "geo:0,0?q=${latitude},${longitude}&z=17&label=${
|
||||
annotation = "geo:0,0?q=$latitude,$longitude&z=17&label=${
|
||||
URLEncoder.encode(nodeName, "utf-8")
|
||||
}"
|
||||
)
|
||||
|
|
|
@ -60,7 +60,7 @@ internal fun MessageItem(
|
|||
) {
|
||||
val fromLocal = shortName == null
|
||||
val messageColor = if (fromLocal) R.color.colorMyMsg else R.color.colorMsg
|
||||
val (topStart, topEnd) = if (fromLocal) 12.dp to 4.dp else 4.dp to 12.dp
|
||||
val (topStart, topEnd) = if (fromLocal) 12.dp to 4.dp else 4.dp to 12.dp
|
||||
val messageModifier = if (fromLocal) {
|
||||
Modifier.padding(start = 48.dp, top = 8.dp, end = 8.dp, bottom = 6.dp)
|
||||
} else {
|
||||
|
|
|
@ -104,7 +104,8 @@ class MessagesFragment : Fragment(), Logging {
|
|||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = MessagesFragmentBinding.inflate(inflater, container, false)
|
||||
|
@ -278,8 +279,9 @@ class MessagesFragment : Fragment(), Logging {
|
|||
selectedList.forEach {
|
||||
resendText = resendText + it.text + System.lineSeparator()
|
||||
}
|
||||
if (resendText != "")
|
||||
if (resendText != "") {
|
||||
resendText = resendText.substring(0, resendText.length - 1)
|
||||
}
|
||||
binding.messageInputText.setText(resendText)
|
||||
mode.finish()
|
||||
}
|
||||
|
|
|
@ -90,9 +90,9 @@ fun NodeItem(
|
|||
}
|
||||
val (textColor, nodeColor) = thatNode.colors
|
||||
|
||||
val hwInfoString = thatNode.user.hwModel.let { hwModel ->
|
||||
if (hwModel == MeshProtos.HardwareModel.UNSET) MeshProtos.HardwareModel.UNSET.name
|
||||
else hwModel.name.replace('_', '-').replace('p', '.').lowercase()
|
||||
val hwInfoString = when (val hwModel = thatNode.user.hwModel) {
|
||||
MeshProtos.HardwareModel.UNSET -> MeshProtos.HardwareModel.UNSET.name
|
||||
else -> hwModel.name.replace('_', '-').replace('p', '.').lowercase()
|
||||
}
|
||||
val roleName = if (isUnknownUser) {
|
||||
DeviceConfig.Role.UNRECOGNIZED.name
|
||||
|
|
|
@ -60,7 +60,8 @@ class QuickChatSettingsFragment : ScreenFragment("Quick Chat Settings"), Logging
|
|||
private val model: UIViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = QuickChatSettingsFragmentBinding.inflate(inflater, container, false)
|
||||
|
@ -81,11 +82,12 @@ class QuickChatSettingsFragment : ScreenFragment("Quick Chat Settings"), Logging
|
|||
|
||||
val name = builder.nameInput.text.toString().trim()
|
||||
val message = builder.messageInput.text.toString()
|
||||
if (builder.isNotEmpty())
|
||||
if (builder.isNotEmpty()) {
|
||||
model.addQuickChatAction(
|
||||
name, message,
|
||||
if (builder.modeSwitch.isChecked) QuickChatAction.Mode.Instant else QuickChatAction.Mode.Append
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val dialog = builder.builder.create()
|
||||
|
|
|
@ -53,7 +53,8 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
private val hasGps by lazy { requireContext().hasGps() }
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = SettingsFragmentBinding.inflate(inflater, container, false)
|
||||
|
@ -86,8 +87,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
|
||||
debug("current region is $region")
|
||||
var regionIndex = regions.indexOfFirst { it.regionCode == region }
|
||||
if (regionIndex == -1) // Not found, probably because the device has a region our app doesn't yet understand. Punt and say Unset
|
||||
if (regionIndex == -1) { // Not found, probably because the device has a region our app doesn't yet understand. Punt and say Unset
|
||||
regionIndex = ConfigProtos.Config.LoRaConfig.RegionCode.UNSET_VALUE
|
||||
}
|
||||
|
||||
// We don't want to be notified of our own changes, so turn off listener while making them
|
||||
spinner.setSelection(regionIndex, false)
|
||||
|
@ -125,7 +127,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>) {
|
||||
//TODO("Not yet implemented")
|
||||
// TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,7 +250,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
if (view.isPressed) { // We want to ignore changes caused by code (as opposed to the user)
|
||||
debug("User changed location tracking to $isChecked")
|
||||
model.provideLocation.value = isChecked
|
||||
if (isChecked && !view.isChecked)
|
||||
if (isChecked && !view.isChecked) {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.background_required)
|
||||
.setMessage(R.string.why_background_required)
|
||||
|
@ -262,6 +264,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
}
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
if (view.isChecked) {
|
||||
checkLocationEnabled(getString(R.string.location_disabled))
|
||||
|
@ -330,8 +333,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
scanModel.showMockInterface()
|
||||
}
|
||||
}
|
||||
if (!device.bonded) // If user just clicked on us, try to bond
|
||||
if (!device.bonded) { // If user just clicked on us, try to bond
|
||||
binding.scanStatusText.setText(R.string.starting_pairing)
|
||||
}
|
||||
b.isChecked = scanModel.onSelected(device)
|
||||
}
|
||||
}
|
||||
|
@ -363,10 +367,11 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
devices.values
|
||||
// Display the device list in alphabetical order while keeping the "None (Disabled)"
|
||||
// device (fullAddress == n) at the top
|
||||
.sortedBy { dle -> if (dle.fullAddress == "n") "0" else dle.name }
|
||||
.sortedBy { dle -> if (dle.fullAddress == "n") "0" else dle.name }
|
||||
.forEach { device ->
|
||||
if (device.fullAddress == scanModel.selectedNotNull)
|
||||
if (device.fullAddress == scanModel.selectedNotNull) {
|
||||
hasShownOurDevice = true
|
||||
}
|
||||
addDeviceButton(device, true)
|
||||
}
|
||||
|
||||
|
@ -473,8 +478,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
if (scanModel.selectedBluetooth) checkBTEnabled()
|
||||
|
||||
// Warn user if provide location is selected but location disabled
|
||||
if (binding.provideLocationCheckbox.isChecked)
|
||||
if (binding.provideLocationCheckbox.isChecked) {
|
||||
checkLocationEnabled(getString(R.string.location_disabled))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -486,7 +492,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
const val SCAN_PERIOD: Long = 10000 // Stops scanning after 10 seconds
|
||||
private const val TAP_TRIGGER: Int = 7
|
||||
private const val TAP_THRESHOLD: Long = 500 // max 500 ms between taps
|
||||
|
||||
}
|
||||
|
||||
private fun Editable.isIPAddress(): Boolean {
|
||||
|
@ -497,5 +502,4 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
Patterns.IP_ADDRESS.matcher(this).matches()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -110,7 +110,6 @@ class UsersFragment : ScreenFragment("Users"), Logging {
|
|||
parentFragmentManager.navigateToMetrics(nodeNum)
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
|
|
@ -37,8 +37,11 @@ fun BitwisePreference(
|
|||
subtitle = value.toString(),
|
||||
onClick = { dropDownExpanded = !dropDownExpanded },
|
||||
enabled = enabled,
|
||||
trailingIcon = if (dropDownExpanded) Icons.TwoTone.KeyboardArrowUp
|
||||
else Icons.TwoTone.KeyboardArrowDown,
|
||||
trailingIcon = if (dropDownExpanded) {
|
||||
Icons.TwoTone.KeyboardArrowUp
|
||||
} else {
|
||||
Icons.TwoTone.KeyboardArrowDown
|
||||
},
|
||||
)
|
||||
|
||||
Box {
|
||||
|
|
|
@ -53,7 +53,6 @@ import com.geeksville.mesh.ui.components.CommonCharts.MS_PER_SEC
|
|||
import com.geeksville.mesh.ui.components.CommonCharts.TIME_FORMAT
|
||||
import com.geeksville.mesh.ui.theme.Orange
|
||||
|
||||
|
||||
private val DEVICE_METRICS_COLORS = listOf(Color.Green, Color.Magenta, Color.Cyan)
|
||||
private const val MAX_PERCENT_VALUE = 100f
|
||||
|
||||
|
@ -64,8 +63,9 @@ fun DeviceMetricsScreen(telemetries: List<Telemetry>) {
|
|||
|
||||
Column {
|
||||
|
||||
if (displayInfoDialog)
|
||||
if (displayInfoDialog) {
|
||||
DeviceInfoDialog { displayInfoDialog = false }
|
||||
}
|
||||
|
||||
DeviceMetricsChart(
|
||||
modifier = Modifier
|
||||
|
@ -92,8 +92,7 @@ private fun DeviceMetricsChart(
|
|||
) {
|
||||
|
||||
ChartHeader(amount = telemetries.size)
|
||||
if (telemetries.isEmpty())
|
||||
return
|
||||
if (telemetries.isEmpty()) return
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
|
@ -153,8 +152,9 @@ private fun DeviceMetricsChart(
|
|||
|
||||
val x2 = spacing + (i + 1) * spacePerEntry
|
||||
val y2 = height - spacing - (rightRatio * height)
|
||||
if (i == 0)
|
||||
if (i == 0) {
|
||||
moveTo(x1, y1)
|
||||
}
|
||||
|
||||
lastX = (x1 + x2) / 2f
|
||||
|
||||
|
|
|
@ -56,8 +56,11 @@ fun <T> DropDownPreference(
|
|||
dropDownExpanded = true
|
||||
},
|
||||
enabled = enabled,
|
||||
trailingIcon = if (dropDownExpanded) Icons.TwoTone.KeyboardArrowUp
|
||||
else Icons.TwoTone.KeyboardArrowDown,
|
||||
trailingIcon = if (dropDownExpanded) {
|
||||
Icons.TwoTone.KeyboardArrowUp
|
||||
} else {
|
||||
Icons.TwoTone.KeyboardArrowDown
|
||||
},
|
||||
summary = summary,
|
||||
)
|
||||
|
||||
|
@ -74,15 +77,17 @@ fun <T> DropDownPreference(
|
|||
},
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = if (selectedItem == item.first)
|
||||
color = if (selectedItem == item.first) {
|
||||
MaterialTheme.colors.primary.copy(alpha = 0.3f)
|
||||
else
|
||||
Color.Unspecified,
|
||||
} else {
|
||||
Color.Unspecified
|
||||
},
|
||||
),
|
||||
content = {
|
||||
Text(
|
||||
text = item.second,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -21,11 +21,13 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusState
|
||||
import androidx.compose.ui.focus.onFocusEvent
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.geeksville.mesh.R
|
||||
|
||||
@Composable
|
||||
fun EditTextPreference(
|
||||
|
@ -167,8 +169,12 @@ fun EditTextPreference(
|
|||
trailingIcon = {
|
||||
if (trailingIcon != null) {
|
||||
trailingIcon()
|
||||
} else {
|
||||
if (isError) Icon(Icons.TwoTone.Info, "Error", tint = MaterialTheme.colors.error)
|
||||
} else if (isError) {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.Info,
|
||||
contentDescription = stringResource(id = R.string.error),
|
||||
tint = MaterialTheme.colors.error
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
@ -54,8 +54,6 @@ enum class Iaq(val color: Color, val description: String, val range: IntRange) {
|
|||
DangerouslyPolluted(Color(0xFF663300), "Dangerously Polluted", 501..Int.MAX_VALUE)
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun getIaq(iaq: Int): Iaq {
|
||||
return when {
|
||||
iaq in Iaq.Excellent.range -> Iaq.Excellent
|
||||
|
@ -70,7 +68,7 @@ fun getIaq(iaq: Int): Iaq {
|
|||
}
|
||||
|
||||
private fun getIaqDescriptionWithRange(iaqEnum: Iaq): String {
|
||||
return if (iaqEnum.range.last == Int.MAX_VALUE){
|
||||
return if (iaqEnum.range.last == Int.MAX_VALUE) {
|
||||
"${iaqEnum.description} (${iaqEnum.range.first}+)"
|
||||
} else {
|
||||
"${iaqEnum.description} (${iaqEnum.range.first}-${iaqEnum.range.last})"
|
||||
|
|
|
@ -31,7 +31,7 @@ fun SimpleAlertDialog(
|
|||
onClick = onDismiss,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp),
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
contentColor = MaterialTheme.colors.onSurface,
|
||||
),
|
||||
) { Text(text = stringResource(id = R.string.close)) }
|
||||
|
|
|
@ -39,7 +39,11 @@ fun SwitchPreference(
|
|||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = if (!enabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) else Color.Unspecified,
|
||||
color = if (enabled) {
|
||||
Color.Unspecified
|
||||
} else {
|
||||
MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled)
|
||||
},
|
||||
)
|
||||
Switch(
|
||||
modifier = modifier
|
||||
|
|
|
@ -59,8 +59,9 @@ fun BluetoothConfigItemList(
|
|||
enabled = enabled,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = {
|
||||
if (it.toString().length == 6) // ensure 6 digits
|
||||
if (it.toString().length == 6) { // ensure 6 digits
|
||||
bluetoothInput = bluetoothInput.copy { fixedPin = it }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ fun CannedMessageConfigItemList(
|
|||
},
|
||||
onSaveClicked = {
|
||||
focusManager.clearFocus()
|
||||
onSaveClicked(messagesInput,cannedMessageInput)
|
||||
onSaveClicked(messagesInput, cannedMessageInput)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -78,8 +78,11 @@ private fun ChannelItem(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(vertical = 4.dp, horizontal = 4.dp)
|
||||
) {
|
||||
val textColor = if (enabled) Color.Unspecified
|
||||
else MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled)
|
||||
val textColor = if (enabled) {
|
||||
Color.Unspecified
|
||||
} else {
|
||||
MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled)
|
||||
}
|
||||
|
||||
Chip(onClick = onClick) {
|
||||
Text(
|
||||
|
@ -165,8 +168,8 @@ fun ChannelSettingsItemList(
|
|||
}
|
||||
}
|
||||
|
||||
val isEditing: Boolean = settingsList.size != settingsListInput.size
|
||||
|| settingsList.zip(settingsListInput).any { (item1, item2) -> item1 != item2 }
|
||||
val isEditing: Boolean = settingsList.size != settingsListInput.size ||
|
||||
settingsList.zip(settingsListInput).any { (item1, item2) -> item1 != item2 }
|
||||
|
||||
var showEditChannelDialog: Int? by rememberSaveable { mutableStateOf(null) }
|
||||
|
||||
|
@ -178,8 +181,11 @@ fun ChannelSettingsItemList(
|
|||
},
|
||||
modemPresetName = modemPresetName,
|
||||
onAddClick = {
|
||||
if (settingsListInput.size > index) settingsListInput[index] = it
|
||||
else settingsListInput.add(it)
|
||||
if (settingsListInput.size > index) {
|
||||
settingsListInput[index] = it
|
||||
} else {
|
||||
settingsListInput.add(it)
|
||||
}
|
||||
showEditChannelDialog = null
|
||||
},
|
||||
onDismissRequest = { showEditChannelDialog = null }
|
||||
|
|
|
@ -25,7 +25,7 @@ import com.geeksville.mesh.ui.components.PreferenceCategory
|
|||
import com.geeksville.mesh.ui.components.PreferenceFooter
|
||||
import com.geeksville.mesh.ui.components.SwitchPreference
|
||||
|
||||
private val DeviceConfig.Role.stringRes: Int
|
||||
private val DeviceConfig.Role.stringRes: Int
|
||||
get() = when (this) {
|
||||
DeviceConfig.Role.CLIENT -> R.string.role_client
|
||||
DeviceConfig.Role.CLIENT_MUTE -> R.string.role_client_mute
|
||||
|
|
|
@ -153,7 +153,6 @@ fun DisplayConfigItemList(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
|
|
|
@ -68,7 +68,7 @@ fun EditDeviceProfileDialog(
|
|||
SwitchPreference(
|
||||
title = field.name,
|
||||
checked = state[field] == true,
|
||||
enabled = deviceProfile.hasField(field),
|
||||
enabled = deviceProfile.hasField(field),
|
||||
onCheckedChange = { state[field] = it },
|
||||
padding = PaddingValues(0.dp)
|
||||
)
|
||||
|
|
|
@ -140,8 +140,9 @@ fun LoRaConfigItemList(
|
|||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onFocusChanged = { isFocused = it.isFocused },
|
||||
onValueChanged = {
|
||||
if (it <= loraInput.numChannels) // total num of LoRa channels
|
||||
if (it <= loraInput.numChannels) { // total num of LoRa channels
|
||||
loraInput = loraInput.copy { channelNum = it }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -97,8 +97,9 @@ fun PositionConfigItemList(
|
|||
enabled = enabled,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = { value ->
|
||||
if (value >= -90 && value <= 90.0)
|
||||
if (value >= -90 && value <= 90.0) {
|
||||
locationInput = locationInput.copy(latitude = value)
|
||||
}
|
||||
})
|
||||
}
|
||||
item {
|
||||
|
@ -107,8 +108,9 @@ fun PositionConfigItemList(
|
|||
enabled = enabled,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = { value ->
|
||||
if (value >= -180 && value <= 180.0)
|
||||
if (value >= -180 && value <= 180.0) {
|
||||
locationInput = locationInput.copy(longitude = value)
|
||||
}
|
||||
})
|
||||
}
|
||||
item {
|
||||
|
|
|
@ -58,8 +58,9 @@ fun UserConfigItemList(
|
|||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChanged = {
|
||||
userInput = userInput.copy { longName = it }
|
||||
if (getInitials(it).toByteArray().size <= 4) // short_name max_size:5
|
||||
if (getInitials(it).toByteArray().size <= 4) { // short_name max_size:5
|
||||
userInput = userInput.copy { shortName = getInitials(it) }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,6 @@ private fun Context.purgeTileSource(onResult: (String) -> Unit) {
|
|||
} else {
|
||||
selectedList.remove(i)
|
||||
}
|
||||
|
||||
}
|
||||
builder.setPositiveButton(R.string.clear) { _, _ ->
|
||||
for (x in selectedList) {
|
||||
|
@ -382,12 +381,13 @@ fun MapView(
|
|||
debug("User deleted waypoint ${waypoint.id} for me")
|
||||
model.deleteWaypoint(waypoint.id)
|
||||
}
|
||||
if (waypoint.lockedTo in setOf(0, model.myNodeNum ?: 0) && model.isConnected())
|
||||
if (waypoint.lockedTo in setOf(0, model.myNodeNum ?: 0) && model.isConnected()) {
|
||||
builder.setPositiveButton(R.string.delete_for_everyone) { _, _ ->
|
||||
debug("User deleted waypoint ${waypoint.id} for everyone")
|
||||
model.sendWaypoint(waypoint.copy { expire = 1 })
|
||||
model.deleteWaypoint(waypoint.id)
|
||||
}
|
||||
}
|
||||
val dialog = builder.show()
|
||||
for (button in setOf(
|
||||
androidx.appcompat.app.AlertDialog.BUTTON_NEUTRAL,
|
||||
|
@ -398,7 +398,7 @@ fun MapView(
|
|||
|
||||
fun showMarkerLongPressDialog(id: Int) {
|
||||
performHapticFeedback()
|
||||
debug("marker long pressed id=${id}")
|
||||
debug("marker long pressed id=$id")
|
||||
val waypoint = waypoints[id]?.data?.waypoint ?: return
|
||||
// edit only when unlocked or lockedTo myNodeNum
|
||||
if (waypoint.lockedTo in setOf(0, model.myNodeNum ?: 0) && model.isConnected()) {
|
||||
|
@ -488,7 +488,7 @@ fun MapView(
|
|||
overlays.add(nodeClusterer)
|
||||
}
|
||||
|
||||
addCopyright() // Copyright is required for certain map sources
|
||||
addCopyright() // Copyright is required for certain map sources
|
||||
createLatLongGrid(false)
|
||||
|
||||
invalidate()
|
||||
|
@ -697,12 +697,18 @@ fun MapView(
|
|||
)
|
||||
MapButton(
|
||||
onClick = {
|
||||
if (context.hasLocationPermission()) map.toggleMyLocation()
|
||||
else requestPermissionAndToggleLauncher.launch(context.getLocationPermissions())
|
||||
if (context.hasLocationPermission()) {
|
||||
map.toggleMyLocation()
|
||||
} else {
|
||||
requestPermissionAndToggleLauncher.launch(context.getLocationPermissions())
|
||||
}
|
||||
},
|
||||
enabled = hasGps,
|
||||
drawableRes = if (myLocationOverlay == null) R.drawable.ic_twotone_my_location_24
|
||||
else R.drawable.ic_twotone_location_disabled_24,
|
||||
drawableRes = if (myLocationOverlay == null) {
|
||||
R.drawable.ic_twotone_my_location_24
|
||||
} else {
|
||||
R.drawable.ic_twotone_location_disabled_24
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
@ -720,7 +726,6 @@ fun MapView(
|
|||
expire = Int.MAX_VALUE // TODO add expire picker
|
||||
lockedTo = if (waypoint.lockedTo != 0) model.myNodeNum ?: 0 else 0
|
||||
})
|
||||
|
||||
},
|
||||
onDeleteClicked = { waypoint ->
|
||||
debug("User clicked delete waypoint ${waypoint.id}")
|
||||
|
|
|
@ -20,7 +20,7 @@ val Any?.anonymize: String
|
|||
fun Any?.anonymize(maxLen: Int = 3) =
|
||||
if (this != null) ("..." + this.toString().takeLast(maxLen)) else "null"
|
||||
|
||||
/// A toString that makes sure all newlines are removed (for nice logging).
|
||||
// A toString that makes sure all newlines are removed (for nice logging).
|
||||
fun Any.toOneLineString() = this.toString().replace('\n', ' ')
|
||||
|
||||
fun ConfigProtos.Config.toOneLineString(): String {
|
||||
|
@ -30,12 +30,13 @@ fun ConfigProtos.Config.toOneLineString(): String {
|
|||
.replace('\n', ' ')
|
||||
}
|
||||
|
||||
/// Return a one line string version of an object (but if a release build, just say 'might be PII)
|
||||
// Return a one line string version of an object (but if a release build, just say 'might be PII)
|
||||
fun Any.toPIIString() =
|
||||
if (!BuildConfig.DEBUG)
|
||||
if (!BuildConfig.DEBUG) {
|
||||
"<PII?>"
|
||||
else
|
||||
} else {
|
||||
this.toOneLineString()
|
||||
}
|
||||
|
||||
fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
|
||||
|
||||
|
@ -51,7 +52,7 @@ fun formatAgo(lastSeenUnix: Int, currentTimeMillis: Long = System.currentTimeMil
|
|||
}
|
||||
}
|
||||
|
||||
/// Allows usage like email.onEditorAction(EditorInfo.IME_ACTION_NEXT, { confirm() })
|
||||
// Allows usage like email.onEditorAction(EditorInfo.IME_ACTION_NEXT, { confirm() })
|
||||
fun EditText.onEditorAction(actionId: Int, func: () -> Unit) {
|
||||
setOnEditorActionListener { _, receivedActionId, _ ->
|
||||
|
||||
|
|
|
@ -21,8 +21,11 @@ object LanguageUtils : Logging {
|
|||
|
||||
fun setLocale(lang: String) {
|
||||
AppCompatDelegate.setApplicationLocales(
|
||||
if (lang == SYSTEM_DEFAULT) LocaleListCompat.getEmptyLocaleList()
|
||||
else LocaleListCompat.forLanguageTags(lang)
|
||||
if (lang == SYSTEM_DEFAULT) {
|
||||
LocaleListCompat.getEmptyLocaleList()
|
||||
} else {
|
||||
LocaleListCompat.forLanguageTags(lang)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -64,4 +67,4 @@ object LanguageUtils : Logging {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,68 @@
|
|||
<SmellBaseline>
|
||||
<ManuallySuppressedIssues></ManuallySuppressedIssues>
|
||||
<CurrentIssues>
|
||||
<ID>ChainWrapping:Channel.kt$Channel$&&</ID>
|
||||
<ID>ChainWrapping:CustomTileSource.kt$CustomTileSource.Companion.<no name provided>$+</ID>
|
||||
<ID>ChainWrapping:SqlTileWriterExt.kt$SqlTileWriterExt$+</ID>
|
||||
<ID>CommentSpacing:AppIntroduction.kt$AppIntroduction$//addSlide(SlideTwoFragment())</ID>
|
||||
<ID>CommentSpacing:BLEException.kt$BLEConnectionClosing$/// Our interface is being shut down</ID>
|
||||
<ID>CommentSpacing:BTScanModel.kt$BTScanModel$/// Use the string for the NopInterface</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// Attempt to read from the fromRadio mailbox, if data is found broadcast it to android apps</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// For testing</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// Our BLE device</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// Our service - note - it is possible to get back a null response for getService if the device services haven't yet been found</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// Send a packet/command out the radio link</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// Start a connection attempt</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// We gracefully handle safe being null because this can occur if someone has unpaired from our device - just abandon the reconnect attempt</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// We only force service refresh the _first_ time we connect to the device. Thereafter it is assumed the firmware didn't change</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$/// We only try to set MTU once, because some buggy implementations fail</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface$//needForceRefresh = false // In fact, because of tearing down BLE in sleep on the ESP32, our handle # assignments are not stable across sleep - so we much refetch every time</ID>
|
||||
<ID>CommentSpacing:BluetoothInterface.kt$BluetoothInterface.Companion$/// this service UUID is publicly visible for scanning</ID>
|
||||
<ID>CommentSpacing:Constants.kt$/// a bool true means we expect this condition to continue until, false means device might come back</ID>
|
||||
<ID>CommentSpacing:ContextExtensions.kt$/// Utility function to hide the soft keyboard per stack overflow</ID>
|
||||
<ID>CommentSpacing:ContextExtensions.kt$/// show a toast</ID>
|
||||
<ID>CommentSpacing:Coroutines.kt$/// Wrap launch with an exception handler, FIXME, move into a utility lib</ID>
|
||||
<ID>CommentSpacing:DeferredExecution.kt$DeferredExecution$/// Queue some new work</ID>
|
||||
<ID>CommentSpacing:DeferredExecution.kt$DeferredExecution$/// run all work in the queue and clear it to be ready to accept new work</ID>
|
||||
<ID>CommentSpacing:DownloadButton.kt$//@Composable</ID>
|
||||
<ID>CommentSpacing:DownloadButton.kt$//@Preview(showBackground = true)</ID>
|
||||
<ID>CommentSpacing:DownloadButton.kt$//private fun DownloadButtonPreview() {</ID>
|
||||
<ID>CommentSpacing:DownloadButton.kt$//}</ID>
|
||||
<ID>CommentSpacing:Exceptions.kt$/// Convert any exceptions in this service call into a RemoteException that the client can</ID>
|
||||
<ID>CommentSpacing:Exceptions.kt$/// then handle</ID>
|
||||
<ID>CommentSpacing:Exceptions.kt$Exceptions$/// Set in Application.onCreate</ID>
|
||||
<ID>CommentSpacing:Logging.kt$Logging$/// Kotlin assertions are disabled on android, so instead we use this assert helper</ID>
|
||||
<ID>CommentSpacing:Logging.kt$Logging$/// Report an error (including messaging our crash reporter service if allowed</ID>
|
||||
<ID>CommentSpacing:Logging.kt$Logging.Companion$/// If false debug logs will not be shown (but others might)</ID>
|
||||
<ID>CommentSpacing:Logging.kt$Logging.Companion$/// if false NO logs will be shown, set this in the application based on BuildConfig.DEBUG</ID>
|
||||
<ID>CommentSpacing:MeshServiceStarter.kt$/// Helper function to start running our service</ID>
|
||||
<ID>CommentSpacing:MockInterface.kt$MockInterface$/// Generate a fake node info entry</ID>
|
||||
<ID>CommentSpacing:MockInterface.kt$MockInterface$/// Generate a fake text message from a node</ID>
|
||||
<ID>CommentSpacing:MockInterface.kt$MockInterface$/// Send a fake ack packet back if the sender asked for want_ack</ID>
|
||||
<ID>CommentSpacing:NOAAWmsTileSource.kt$NOAAWmsTileSource$//array indexes for that data</ID>
|
||||
<ID>CommentSpacing:NOAAWmsTileSource.kt$NOAAWmsTileSource$//used by geo server</ID>
|
||||
<ID>CommentSpacing:NodeInfo.kt$NodeInfo$/// @return a nice human readable string for the distance, or null for unknown</ID>
|
||||
<ID>CommentSpacing:NodeInfo.kt$NodeInfo$/// @return bearing to the other position in degrees</ID>
|
||||
<ID>CommentSpacing:NodeInfo.kt$NodeInfo$/// @return distance in meters to some other node (or null if unknown)</ID>
|
||||
<ID>CommentSpacing:NodeInfo.kt$NodeInfo$/// return the position if it is valid, else null</ID>
|
||||
<ID>CommentSpacing:NodeInfo.kt$Position$/// @return bearing to the other position in degrees</ID>
|
||||
<ID>CommentSpacing:NodeInfo.kt$Position$/// @return distance in meters to some other node (or null if unknown)</ID>
|
||||
<ID>CommentSpacing:NodeInfo.kt$Position.Companion$/// Convert to a double representation of degrees</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$/// Return a standard BLE 128 bit UUID from the short 16 bit versions</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// Drop our current connection and then requeue a connect as needed</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// If we have work we can do, start doing it.</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// Restart any previous connect attempts</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// Timeout before we declare a bluetooth operation failed (used for synchronous API operations only)</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// True if the current active connection is auto (possible for this to be false but autoConnect to be true</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// Users can access the GATT directly as needed</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// asyncronously turn notification on/off for a characteristic</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// from characteristic UUIDs to the handler function for notfies</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// helper glue to make sync continuations and then wait for the result</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$/// if we are in the first non-automated lowLevel connect.</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth$//com.geeksville.mesh.service.SafeBluetooth.closeGatt</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth.<no name provided>$//throw Exception("Mystery bluetooth failure - debug me")</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth.BluetoothContinuation$/// Connection work items are treated specially</ID>
|
||||
<ID>CommentSpacing:SafeBluetooth.kt$SafeBluetooth.BluetoothContinuation$/// Start running a queued bit of work, return true for success or false for fatal bluetooth error</ID>
|
||||
<ID>ConstructorParameterNaming:MeshLog.kt$MeshLog$@ColumnInfo(name = "message") val raw_message: String</ID>
|
||||
<ID>ConstructorParameterNaming:MeshLog.kt$MeshLog$@ColumnInfo(name = "received_date") val received_date: Long</ID>
|
||||
<ID>ConstructorParameterNaming:MeshLog.kt$MeshLog$@ColumnInfo(name = "type") val message_type: String</ID>
|
||||
|
@ -10,15 +72,11 @@
|
|||
<ID>ConstructorParameterNaming:Packet.kt$Packet$@ColumnInfo(name = "port_num") val port_num: Int</ID>
|
||||
<ID>ConstructorParameterNaming:Packet.kt$Packet$@ColumnInfo(name = "received_time") val received_time: Long</ID>
|
||||
<ID>CyclomaticComplexMethod:ChannelFragment.kt$@Composable fun ChannelScreen( viewModel: UIViewModel = viewModel(), showSnackbar: (String) -> Unit = {}, )</ID>
|
||||
<ID>CyclomaticComplexMethod:DeviceSettingsFragment.kt$@Composable fun RadioConfigNavHost( node: NodeInfo?, viewModel: RadioConfigViewModel = hiltViewModel(), navController: NavHostController = rememberNavController(), modifier: Modifier, )</ID>
|
||||
<ID>CyclomaticComplexMethod:MainActivity.kt$MainActivity$override fun onOptionsItemSelected(item: MenuItem): Boolean</ID>
|
||||
<ID>CyclomaticComplexMethod:MapFragment.kt$@Composable fun MapView( model: UIViewModel = viewModel(), )</ID>
|
||||
<ID>CyclomaticComplexMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)</ID>
|
||||
<ID>CyclomaticComplexMethod:PositionConfigItemList.kt$@Composable fun PositionConfigItemList( isLocal: Boolean = false, location: Position?, positionConfig: PositionConfig, enabled: Boolean, onSaveClicked: (position: Position?, config: PositionConfig) -> Unit, )</ID>
|
||||
<ID>CyclomaticComplexMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)</ID>
|
||||
<ID>CyclomaticComplexMethod:SettingsFragment.kt$SettingsFragment$private fun initCommonUI()</ID>
|
||||
<ID>CyclomaticComplexMethod:UIState.kt$UIViewModel$fun saveMessagesCSV(uri: Uri)</ID>
|
||||
<ID>DestructuringDeclarationWithTooManyEntries:NodeInfo.kt$val (chip, dist, name, hw, pos, alt, sats, batt, heard, sig, env) = createRefs()</ID>
|
||||
<ID>EmptyCatchBlock:MeshLog.kt$MeshLog${ }</ID>
|
||||
<ID>EmptyClassBlock:DebugLogFile.kt$BinaryLogFile${ }</ID>
|
||||
<ID>EmptyDefaultConstructor:SqlTileWriterExt.kt$SqlTileWriterExt$()</ID>
|
||||
|
@ -27,7 +85,54 @@
|
|||
<ID>EmptyFunctionBlock:NopInterface.kt$NopInterface${ }</ID>
|
||||
<ID>EmptyFunctionBlock:NsdManager.kt$<no name provided>${ }</ID>
|
||||
<ID>EmptyFunctionBlock:TrustAllX509TrustManager.kt$TrustAllX509TrustManager${}</ID>
|
||||
<ID>ExceptionRaisedInUnexpectedLocation:DistanceExtensions.kt$fun Float.toString( system: ConfigProtos.Config.DisplayConfig.DisplayUnits ): String</ID>
|
||||
<ID>FinalNewline:AppIntroduction.kt$com.geeksville.mesh.AppIntroduction.kt</ID>
|
||||
<ID>FinalNewline:AppPrefs.kt$com.geeksville.mesh.android.AppPrefs.kt</ID>
|
||||
<ID>FinalNewline:ApplicationModule.kt$com.geeksville.mesh.ApplicationModule.kt</ID>
|
||||
<ID>FinalNewline:BLEException.kt$com.geeksville.mesh.service.BLEException.kt</ID>
|
||||
<ID>FinalNewline:BluetoothInterfaceFactory.kt$com.geeksville.mesh.repository.radio.BluetoothInterfaceFactory.kt</ID>
|
||||
<ID>FinalNewline:BluetoothRepositoryModule.kt$com.geeksville.mesh.repository.bluetooth.BluetoothRepositoryModule.kt</ID>
|
||||
<ID>FinalNewline:BluetoothViewModel.kt$com.geeksville.mesh.model.BluetoothViewModel.kt</ID>
|
||||
<ID>FinalNewline:BootCompleteReceiver.kt$com.geeksville.mesh.service.BootCompleteReceiver.kt</ID>
|
||||
<ID>FinalNewline:Color.kt$com.geeksville.mesh.ui.theme.Color.kt</ID>
|
||||
<ID>FinalNewline:CoroutineDispatchers.kt$com.geeksville.mesh.CoroutineDispatchers.kt</ID>
|
||||
<ID>FinalNewline:Coroutines.kt$com.geeksville.mesh.concurrent.Coroutines.kt</ID>
|
||||
<ID>FinalNewline:CustomTileSource.kt$com.geeksville.mesh.model.map.CustomTileSource.kt</ID>
|
||||
<ID>FinalNewline:DatabaseModule.kt$com.geeksville.mesh.database.DatabaseModule.kt</ID>
|
||||
<ID>FinalNewline:DateUtils.kt$com.geeksville.mesh.android.DateUtils.kt</ID>
|
||||
<ID>FinalNewline:DebugLogFile.kt$com.geeksville.mesh.android.DebugLogFile.kt</ID>
|
||||
<ID>FinalNewline:DeferredExecution.kt$com.geeksville.mesh.concurrent.DeferredExecution.kt</ID>
|
||||
<ID>FinalNewline:DeviceVersion.kt$com.geeksville.mesh.model.DeviceVersion.kt</ID>
|
||||
<ID>FinalNewline:DeviceVersionTest.kt$com.geeksville.mesh.model.DeviceVersionTest.kt</ID>
|
||||
<ID>FinalNewline:ElevationInfo.kt$com.geeksville.mesh.ui.compose.ElevationInfo.kt</ID>
|
||||
<ID>FinalNewline:ExpireChecker.kt$com.geeksville.mesh.android.ExpireChecker.kt</ID>
|
||||
<ID>FinalNewline:InterfaceId.kt$com.geeksville.mesh.repository.radio.InterfaceId.kt</ID>
|
||||
<ID>FinalNewline:InterfaceSpec.kt$com.geeksville.mesh.repository.radio.InterfaceSpec.kt</ID>
|
||||
<ID>FinalNewline:Logging.kt$com.geeksville.mesh.android.Logging.kt</ID>
|
||||
<ID>FinalNewline:MockInterfaceFactory.kt$com.geeksville.mesh.repository.radio.MockInterfaceFactory.kt</ID>
|
||||
<ID>FinalNewline:NOAAWmsTileSource.kt$com.geeksville.mesh.model.map.NOAAWmsTileSource.kt</ID>
|
||||
<ID>FinalNewline:NopInterface.kt$com.geeksville.mesh.repository.radio.NopInterface.kt</ID>
|
||||
<ID>FinalNewline:NopInterfaceFactory.kt$com.geeksville.mesh.repository.radio.NopInterfaceFactory.kt</ID>
|
||||
<ID>FinalNewline:OnlineTileSourceAuth.kt$com.geeksville.mesh.model.map.OnlineTileSourceAuth.kt</ID>
|
||||
<ID>FinalNewline:PreferenceCategory.kt$com.geeksville.mesh.ui.components.PreferenceCategory.kt</ID>
|
||||
<ID>FinalNewline:PreviewParameterProviders.kt$com.geeksville.mesh.ui.preview.PreviewParameterProviders.kt</ID>
|
||||
<ID>FinalNewline:ProbeTableProvider.kt$com.geeksville.mesh.repository.usb.ProbeTableProvider.kt</ID>
|
||||
<ID>FinalNewline:QuickChatActionDao.kt$com.geeksville.mesh.database.dao.QuickChatActionDao.kt</ID>
|
||||
<ID>FinalNewline:QuickChatActionRepository.kt$com.geeksville.mesh.database.QuickChatActionRepository.kt</ID>
|
||||
<ID>FinalNewline:RadioNotConnectedException.kt$com.geeksville.mesh.service.RadioNotConnectedException.kt</ID>
|
||||
<ID>FinalNewline:RadioRepositoryModule.kt$com.geeksville.mesh.repository.radio.RadioRepositoryModule.kt</ID>
|
||||
<ID>FinalNewline:RegularPreference.kt$com.geeksville.mesh.ui.components.RegularPreference.kt</ID>
|
||||
<ID>FinalNewline:SafeBluetooth.kt$com.geeksville.mesh.service.SafeBluetooth.kt</ID>
|
||||
<ID>FinalNewline:SatelliteCountInfo.kt$com.geeksville.mesh.ui.compose.SatelliteCountInfo.kt</ID>
|
||||
<ID>FinalNewline:SerialConnection.kt$com.geeksville.mesh.repository.usb.SerialConnection.kt</ID>
|
||||
<ID>FinalNewline:SerialConnectionListener.kt$com.geeksville.mesh.repository.usb.SerialConnectionListener.kt</ID>
|
||||
<ID>FinalNewline:SerialInterface.kt$com.geeksville.mesh.repository.radio.SerialInterface.kt</ID>
|
||||
<ID>FinalNewline:SerialInterfaceFactory.kt$com.geeksville.mesh.repository.radio.SerialInterfaceFactory.kt</ID>
|
||||
<ID>FinalNewline:SoftwareUpdateService.kt$com.geeksville.mesh.service.SoftwareUpdateService.kt</ID>
|
||||
<ID>FinalNewline:SqlTileWriterExt.kt$com.geeksville.mesh.util.SqlTileWriterExt.kt</ID>
|
||||
<ID>FinalNewline:TCPInterfaceFactory.kt$com.geeksville.mesh.repository.radio.TCPInterfaceFactory.kt</ID>
|
||||
<ID>FinalNewline:Theme.kt$com.geeksville.mesh.ui.theme.Theme.kt</ID>
|
||||
<ID>FinalNewline:UsbBroadcastReceiver.kt$com.geeksville.mesh.repository.usb.UsbBroadcastReceiver.kt</ID>
|
||||
<ID>FinalNewline:UsbRepositoryModule.kt$com.geeksville.mesh.repository.usb.UsbRepositoryModule.kt</ID>
|
||||
<ID>ForbiddenComment:MapFragment.kt$// TODO: Accept filename input param from user</ID>
|
||||
<ID>ForbiddenComment:SafeBluetooth.kt$SafeBluetooth$// TODO: display some kind of UI about restarting BLE</ID>
|
||||
<ID>FunctionNaming:PacketDao.kt$PacketDao$@Query("DELETE FROM packet WHERE uuid=:uuid") fun _delete(uuid: Long)</ID>
|
||||
|
@ -41,13 +146,6 @@
|
|||
<ID>ImplicitDefaultLocale:LocationUtils.kt$GPSFormat$String.format( "%s%s %s%s %05d %05d", MGRS.zone, MGRS.band, MGRS.column, MGRS.row, MGRS.easting, MGRS.northing )</ID>
|
||||
<ID>ImplicitDefaultLocale:LocationUtils.kt$GPSFormat$String.format("%.5f %.5f", p.latitude, p.longitude)</ID>
|
||||
<ID>ImplicitDefaultLocale:LocationUtils.kt$GPSFormat$String.format("%s°%s'%.5s\"%s", a[0], a[1], a[2], a[3])</ID>
|
||||
<ID>ImplicitDefaultLocale:NodeInfo.kt$EnvironmentMetrics$String.format("%.0f%%", relativeHumidity)</ID>
|
||||
<ID>ImplicitDefaultLocale:NodeInfo.kt$EnvironmentMetrics$String.format("%.0fMΩ", gasResistance)</ID>
|
||||
<ID>ImplicitDefaultLocale:NodeInfo.kt$EnvironmentMetrics$String.format("%.1fhPa", barometricPressure)</ID>
|
||||
<ID>ImplicitDefaultLocale:NodeInfo.kt$EnvironmentMetrics$String.format("%.1fmA", current)</ID>
|
||||
<ID>ImplicitDefaultLocale:NodeInfo.kt$EnvironmentMetrics$String.format("%.1f°C", temperature)</ID>
|
||||
<ID>ImplicitDefaultLocale:NodeInfo.kt$EnvironmentMetrics$String.format("%.1f°F", fahrenheit)</ID>
|
||||
<ID>ImplicitDefaultLocale:NodeInfo.kt$EnvironmentMetrics$String.format("%.2fV", voltage)</ID>
|
||||
<ID>ImplicitDefaultLocale:NodeInfo.kt$NodeInfo$String.format("%d%%", batteryLevel)</ID>
|
||||
<ID>LargeClass:MeshService.kt$MeshService : ServiceLogging</ID>
|
||||
<ID>LongMethod:AmbientLightingConfigItemList.kt$@Composable fun AmbientLightingConfigItemList( ambientLightingConfig: ModuleConfigProtos.ModuleConfig.AmbientLightingConfig, enabled: Boolean, onSaveClicked: (ModuleConfigProtos.ModuleConfig.AmbientLightingConfig) -> Unit, )</ID>
|
||||
|
@ -55,27 +153,17 @@
|
|||
<ID>LongMethod:CannedMessageConfigItemList.kt$@Composable fun CannedMessageConfigItemList( messages: String, cannedMessageConfig: CannedMessageConfig, enabled: Boolean, onSaveClicked: (messages: String, config: CannedMessageConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:ChannelFragment.kt$@Composable fun ChannelScreen( viewModel: UIViewModel = viewModel(), showSnackbar: (String) -> Unit = {}, )</ID>
|
||||
<ID>LongMethod:ChannelSettingsItemList.kt$@Composable fun ChannelSettingsItemList( settingsList: List<ChannelSettings>, modemPresetName: String = "Default", maxChannels: Int = 8, enabled: Boolean, onNegativeClicked: () -> Unit = { }, onPositiveClicked: (List<ChannelSettings>) -> Unit, )</ID>
|
||||
<ID>LongMethod:ContactItem.kt$@OptIn(ExperimentalMaterialApi::class) @Composable fun ContactItem( contact: Contact, modifier: Modifier = Modifier, )</ID>
|
||||
<ID>LongMethod:ContactsFragment.kt$ContactsFragment.ActionModeCallback$override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean</ID>
|
||||
<ID>LongMethod:DetectionSensorConfigItemList.kt$@Composable fun DetectionSensorConfigItemList( detectionSensorConfig: ModuleConfigProtos.ModuleConfig.DetectionSensorConfig, enabled: Boolean, onSaveClicked: (ModuleConfigProtos.ModuleConfig.DetectionSensorConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:DeviceConfigItemList.kt$@Composable fun DeviceConfigItemList( deviceConfig: DeviceConfig, enabled: Boolean, onSaveClicked: (DeviceConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:DeviceSettingsFragment.kt$@Composable fun RadioConfigNavHost( node: NodeInfo?, viewModel: RadioConfigViewModel = hiltViewModel(), navController: NavHostController = rememberNavController(), modifier: Modifier, )</ID>
|
||||
<ID>LongMethod:DisplayConfigItemList.kt$@Composable fun DisplayConfigItemList( displayConfig: DisplayConfig, enabled: Boolean, onSaveClicked: (DisplayConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:EditChannelDialog.kt$@Composable fun EditChannelDialog( channelSettings: ChannelProtos.ChannelSettings, onAddClick: (ChannelProtos.ChannelSettings) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier, modemPresetName: String = "Default", )</ID>
|
||||
<ID>LongMethod:EditDeviceProfileDialog.kt$@Composable fun EditDeviceProfileDialog( title: String, deviceProfile: ClientOnlyProtos.DeviceProfile, onAddClick: (ClientOnlyProtos.DeviceProfile) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier, )</ID>
|
||||
<ID>LongMethod:DropDownPreference.kt$@Composable fun <T> DropDownPreference( title: String, enabled: Boolean, items: List<Pair<T, String>>, selectedItem: T, onItemSelected: (T) -> Unit, modifier: Modifier = Modifier, summary: String? = null, )</ID>
|
||||
<ID>LongMethod:EditListPreference.kt$@Composable inline fun <reified T> EditListPreference( title: String, list: List<T>, maxCount: Int, enabled: Boolean, keyboardActions: KeyboardActions, crossinline onValuesChanged: (List<T>) -> Unit, modifier: Modifier = Modifier, )</ID>
|
||||
<ID>LongMethod:EditWaypointDialog.kt$@Composable internal fun EditWaypointDialog( waypoint: Waypoint, onSendClicked: (Waypoint) -> Unit, onDeleteClicked: (Waypoint) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier, )</ID>
|
||||
<ID>LongMethod:ExternalNotificationConfigItemList.kt$@Composable fun ExternalNotificationConfigItemList( ringtone: String, extNotificationConfig: ExternalNotificationConfig, enabled: Boolean, onSaveClicked: (ringtone: String, config: ExternalNotificationConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:LoRaConfigItemList.kt$@Composable fun LoRaConfigItemList( loraConfig: LoRaConfig, primarySettings: ChannelSettings, enabled: Boolean, onSaveClicked: (LoRaConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:MQTTConfigItemList.kt$@Composable fun MQTTConfigItemList( mqttConfig: MQTTConfig, enabled: Boolean, onSaveClicked: (MQTTConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:MainActivity.kt$MainActivity$override fun onOptionsItemSelected(item: MenuItem): Boolean</ID>
|
||||
<ID>LongMethod:MapFragment.kt$@Composable fun MapView( model: UIViewModel = viewModel(), )</ID>
|
||||
<ID>LongMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)</ID>
|
||||
<ID>LongMethod:MessagesFragment.kt$MessagesFragment$override fun onViewCreated(view: View, savedInstanceState: Bundle?)</ID>
|
||||
<ID>LongMethod:MessagesFragment.kt$MessagesFragment.<no name provided>$override fun onBindViewHolder(holder: ViewHolder, position: Int)</ID>
|
||||
<ID>LongMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigItemList( networkConfig: NetworkConfig, enabled: Boolean, onSaveClicked: (NetworkConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:NodeInfo.kt$@OptIn(ExperimentalMaterialApi::class) @Composable fun NodeInfo( thisNodeInfo: NodeInfo?, thatNodeInfo: NodeInfo, gpsFormat: Int, distanceUnits: Int, tempInFahrenheit: Boolean, isIgnored: Boolean = false, onClicked: () -> Unit = {}, blinking: Boolean = false, )</ID>
|
||||
<ID>LongMethod:PositionConfigItemList.kt$@Composable fun PositionConfigItemList( isLocal: Boolean = false, location: Position?, positionConfig: PositionConfig, enabled: Boolean, onSaveClicked: (position: Position?, config: PositionConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:PowerConfigItemList.kt$@Composable fun PowerConfigItemList( powerConfig: PowerConfig, enabled: Boolean, onSaveClicked: (PowerConfig) -> Unit, )</ID>
|
||||
<ID>LongMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)</ID>
|
||||
<ID>LongMethod:SerialConfigItemList.kt$@Composable fun SerialConfigItemList( serialConfig: SerialConfig, enabled: Boolean, onSaveClicked: (SerialConfig) -> Unit, )</ID>
|
||||
|
@ -88,7 +176,6 @@
|
|||
<ID>LongParameterList:NOAAWmsTileSource.kt$NOAAWmsTileSource$( aName: String, aBaseUrl: Array<String>, layername: String, version: String, time: String?, srs: String, style: String?, format: String, )</ID>
|
||||
<ID>LongParameterList:OnlineTileSourceAuth.kt$OnlineTileSourceAuth$( aName: String, aZoomLevel: Int, aZoomMaxLevel: Int, aTileSizePixels: Int, aImageFileNameEnding: String, aBaseUrl: Array<String>, pCopyright: String, tileSourcePolicy: TileSourcePolicy, layerName: String?, apiKey: String )</ID>
|
||||
<ID>LongParameterList:RadioInterfaceService.kt$RadioInterfaceService$( private val context: Application, private val dispatchers: CoroutineDispatchers, private val bluetoothRepository: BluetoothRepository, private val networkRepository: NetworkRepository, private val processLifecycle: Lifecycle, @RadioRepositoryQualifier private val prefs: SharedPreferences, private val interfaceFactory: InterfaceFactory, )</ID>
|
||||
<ID>LongParameterList:UIState.kt$UIViewModel$( private val app: Application, val nodeDB: NodeDB, private val radioConfigRepository: RadioConfigRepository, private val radioInterfaceService: RadioInterfaceService, private val meshLogRepository: MeshLogRepository, private val packetRepository: PacketRepository, private val quickChatActionRepository: QuickChatActionRepository, private val preferences: SharedPreferences )</ID>
|
||||
<ID>MagicNumber:BatteryInfo.kt$100</ID>
|
||||
<ID>MagicNumber:BatteryInfo.kt$101</ID>
|
||||
<ID>MagicNumber:BatteryInfo.kt$14</ID>
|
||||
|
@ -128,52 +215,10 @@
|
|||
<ID>MagicNumber:ChannelOption.kt$ChannelOption.SHORT_FAST$.250f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$ChannelOption.SHORT_SLOW$.250f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$ChannelOption.VERY_LONG_SLOW$.0625f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.ANZ$915.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.ANZ$928.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.CN$470.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.CN$510.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.EU_433$433.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.EU_433$434.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.EU_868$869.4f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.EU_868$869.65f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.IN$865.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.IN$867.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.JP$920.8f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.JP$927.8f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.KR$920.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.KR$923.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.LORA_24$2400.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.LORA_24$2483.5f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.MY_433$433.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.MY_433$435.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.MY_919$919.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.MY_919$924.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.NZ_865$864.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.NZ_865$868.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.RU$868.7f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.RU$869.2f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.SG_923$917.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.SG_923$925.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.TH$920.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.TH$925.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.TW$920.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.TW$925.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.UA_433$433.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.UA_433$434.7f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.UA_868$868.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.UA_868$868.6f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.UNSET$902.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.UNSET$928.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.US$902.0f</ID>
|
||||
<ID>MagicNumber:ChannelOption.kt$RegionInfo.US$928.0f</ID>
|
||||
<ID>MagicNumber:ChannelSet.kt$40</ID>
|
||||
<ID>MagicNumber:ChannelSet.kt$960</ID>
|
||||
<ID>MagicNumber:ContactsFragment.kt$ContactsFragment.ActionModeCallback$7</ID>
|
||||
<ID>MagicNumber:ContactsFragment.kt$ContactsFragment.ActionModeCallback$8</ID>
|
||||
<ID>MagicNumber:ContactsViewModel.kt$1000L</ID>
|
||||
<ID>MagicNumber:ContactsViewModel.kt$24</ID>
|
||||
<ID>MagicNumber:ContactsViewModel.kt$60</ID>
|
||||
<ID>MagicNumber:ContextServices.kt$29</ID>
|
||||
<ID>MagicNumber:ContextServices.kt$33</ID>
|
||||
<ID>MagicNumber:DataPacket.kt$DataPacket.CREATOR$16</ID>
|
||||
<ID>MagicNumber:DebugFragment.kt$DebugFragment$3</ID>
|
||||
|
@ -193,9 +238,6 @@
|
|||
<ID>MagicNumber:DeviceSettingsFragment.kt$ModuleRoute.TELEMETRY$5</ID>
|
||||
<ID>MagicNumber:DeviceVersion.kt$DeviceVersion$100</ID>
|
||||
<ID>MagicNumber:DeviceVersion.kt$DeviceVersion$10000</ID>
|
||||
<ID>MagicNumber:DistanceExtensions.kt$DistanceUnit.FEET$3.28084F</ID>
|
||||
<ID>MagicNumber:DistanceExtensions.kt$DistanceUnit.KILOMETERS$0.001F</ID>
|
||||
<ID>MagicNumber:DistanceExtensions.kt$DistanceUnit.MILES$0.000621371F</ID>
|
||||
<ID>MagicNumber:DownloadButton.kt$1.25f</ID>
|
||||
<ID>MagicNumber:EditChannelDialog.kt$16</ID>
|
||||
<ID>MagicNumber:EditChannelDialog.kt$32</ID>
|
||||
|
@ -215,10 +257,7 @@
|
|||
<ID>MagicNumber:Extensions.kt$24</ID>
|
||||
<ID>MagicNumber:Extensions.kt$2880</ID>
|
||||
<ID>MagicNumber:Extensions.kt$60</ID>
|
||||
<ID>MagicNumber:IconButton.kt$1.5f</ID>
|
||||
<ID>MagicNumber:LazyColumnDragAndDropDemo.kt$50</ID>
|
||||
<ID>MagicNumber:LinkedCoordinates.kt$122.4194</ID>
|
||||
<ID>MagicNumber:LinkedCoordinates.kt$37.7749</ID>
|
||||
<ID>MagicNumber:LocationRepository.kt$LocationRepository$1000L</ID>
|
||||
<ID>MagicNumber:LocationRepository.kt$LocationRepository$30</ID>
|
||||
<ID>MagicNumber:LocationRepository.kt$LocationRepository$31</ID>
|
||||
|
@ -226,7 +265,6 @@
|
|||
<ID>MagicNumber:LocationUtils.kt$111320</ID>
|
||||
<ID>MagicNumber:LocationUtils.kt$180</ID>
|
||||
<ID>MagicNumber:LocationUtils.kt$1e-7</ID>
|
||||
<ID>MagicNumber:LocationUtils.kt$3.14169</ID>
|
||||
<ID>MagicNumber:LocationUtils.kt$360</ID>
|
||||
<ID>MagicNumber:LocationUtils.kt$360.0</ID>
|
||||
<ID>MagicNumber:LocationUtils.kt$3600.0</ID>
|
||||
|
@ -249,12 +287,8 @@
|
|||
<ID>MagicNumber:MapFragment.kt$3.0f</ID>
|
||||
<ID>MagicNumber:MapFragment.kt$40f</ID>
|
||||
<ID>MagicNumber:MapFragment.kt$<no name provided>$1e7</ID>
|
||||
<ID>MagicNumber:MarkerWithLabel.kt$MarkerWithLabel$2F</ID>
|
||||
<ID>MagicNumber:MarkerWithLabel.kt$MarkerWithLabel$3</ID>
|
||||
<ID>MagicNumber:MarkerWithLabel.kt$MarkerWithLabel$30f</ID>
|
||||
<ID>MagicNumber:MarkerWithLabel.kt$MarkerWithLabel$8F</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$0xffffffff</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$0xffffffffL</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$100</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$1000</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$1000.0</ID>
|
||||
|
@ -262,8 +296,6 @@
|
|||
<ID>MagicNumber:MeshService.kt$MeshService$16</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$30</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$32</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$5</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$60</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$60000</ID>
|
||||
<ID>MagicNumber:MeshService.kt$MeshService$8</ID>
|
||||
<ID>MagicNumber:MessagesFragment.kt$1000L</ID>
|
||||
|
@ -276,7 +308,6 @@
|
|||
<ID>MagicNumber:MockInterface.kt$MockInterface$2000</ID>
|
||||
<ID>MagicNumber:MockInterface.kt$MockInterface$32.776665</ID>
|
||||
<ID>MagicNumber:MockInterface.kt$MockInterface$32.960758</ID>
|
||||
<ID>MagicNumber:MockInterface.kt$MockInterface$35</ID>
|
||||
<ID>MagicNumber:MockInterface.kt$MockInterface$96.733521</ID>
|
||||
<ID>MagicNumber:MockInterface.kt$MockInterface$96.796989</ID>
|
||||
<ID>MagicNumber:NOAAWmsTileSource.kt$NOAAWmsTileSource$180</ID>
|
||||
|
@ -284,10 +315,7 @@
|
|||
<ID>MagicNumber:NOAAWmsTileSource.kt$NOAAWmsTileSource$360.0</ID>
|
||||
<ID>MagicNumber:NOAAWmsTileSource.kt$NOAAWmsTileSource$4</ID>
|
||||
<ID>MagicNumber:NOAAWmsTileSource.kt$NOAAWmsTileSource$5</ID>
|
||||
<ID>MagicNumber:NodeInfo.kt$0x33FFFFFF</ID>
|
||||
<ID>MagicNumber:NodeInfo.kt$DeviceMetrics.Companion$1000</ID>
|
||||
<ID>MagicNumber:NodeInfo.kt$EnvironmentMetrics$1.8F</ID>
|
||||
<ID>MagicNumber:NodeInfo.kt$EnvironmentMetrics$32</ID>
|
||||
<ID>MagicNumber:NodeInfo.kt$EnvironmentMetrics.Companion$1000</ID>
|
||||
<ID>MagicNumber:NodeInfo.kt$NodeInfo$0.114</ID>
|
||||
<ID>MagicNumber:NodeInfo.kt$NodeInfo$0.299</ID>
|
||||
|
@ -314,9 +342,6 @@
|
|||
<ID>MagicNumber:NodeMenu.kt$3</ID>
|
||||
<ID>MagicNumber:PacketRepository.kt$PacketRepository$500</ID>
|
||||
<ID>MagicNumber:PacketResponseStateDialog.kt$100</ID>
|
||||
<ID>MagicNumber:PositionPrecisionPreference.kt$PositionPrecision.HIGH_PRECISION$32</ID>
|
||||
<ID>MagicNumber:PositionPrecisionPreference.kt$PositionPrecision.LOW_PRECISION$11</ID>
|
||||
<ID>MagicNumber:PositionPrecisionPreference.kt$PositionPrecision.MED_PRECISION$16</ID>
|
||||
<ID>MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$21972</ID>
|
||||
<ID>MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$32809</ID>
|
||||
<ID>MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$6790</ID>
|
||||
|
@ -330,7 +355,6 @@
|
|||
<ID>MagicNumber:SerialConnectionImpl.kt$SerialConnectionImpl$115200</ID>
|
||||
<ID>MagicNumber:SerialConnectionImpl.kt$SerialConnectionImpl$200</ID>
|
||||
<ID>MagicNumber:ServiceClient.kt$ServiceClient$500</ID>
|
||||
<ID>MagicNumber:SignalInfo.kt$100F</ID>
|
||||
<ID>MagicNumber:SoftwareUpdateService.kt$0xFF</ID>
|
||||
<ID>MagicNumber:SoftwareUpdateService.kt$16</ID>
|
||||
<ID>MagicNumber:SoftwareUpdateService.kt$24</ID>
|
||||
|
@ -369,15 +393,10 @@
|
|||
<ID>MaxLineLength:BluetoothInterface.kt$BluetoothInterface$null</ID>
|
||||
<ID>MaxLineLength:BluetoothState.kt$BluetoothState$"BluetoothState(hasPermissions=$hasPermissions, enabled=$enabled, bondedDevices=${bondedDevices.map { it.anonymize }})"</ID>
|
||||
<ID>MaxLineLength:Channel.kt$Channel$// We have a new style 'empty' channel name. Use the same logic from the device to convert that to a human readable name</ID>
|
||||
<ID>MaxLineLength:Channel.kt$Channel$/// Return the name of our channel as a human readable string. If empty string, assume "Default" per mesh.proto spec</ID>
|
||||
<ID>MaxLineLength:ChannelFragment.kt$color = if (!enabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) else Color.Unspecified</ID>
|
||||
<ID>MaxLineLength:ChannelSettingsItemList.kt$color = if (!enabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) else Color.Unspecified</ID>
|
||||
<ID>MaxLineLength:ContextServices.kt$get</ID>
|
||||
<ID>MaxLineLength:ContextServices.kt$val Context.locationManager: LocationManager get() = requireNotNull(getSystemService(Context.LOCATION_SERVICE) as? LocationManager?)</ID>
|
||||
<ID>MaxLineLength:ContextServices.kt$val Context.notificationManager: NotificationManager get() = requireNotNull(getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager?)</ID>
|
||||
<ID>MaxLineLength:CustomTileSource.kt$CustomTileSource.Companion$arrayOf("https://new.nowcoast.noaa.gov/arcgis/services/nowcoast/radar_meteo_imagery_nexrad_time/MapServer/WmsServer?")</ID>
|
||||
<ID>MaxLineLength:DataPacket.kt$DataPacket$val dataType: Int</ID>
|
||||
<ID>MaxLineLength:EditListPreference.kt$color = if (!enabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) else Color.Unspecified</ID>
|
||||
<ID>MaxLineLength:LoRaConfigItemList.kt$value = if (isFocused || loraInput.overrideFrequency != 0f) loraInput.overrideFrequency else primaryChannel.radioFreq</ID>
|
||||
<ID>MaxLineLength:LocationRepository.kt$LocationRepository$info("Starting location updates with $providerList intervalMs=${intervalMs}ms and minDistanceM=${minDistanceM}m")</ID>
|
||||
<ID>MaxLineLength:MQTTRepository.kt$MQTTRepository.Companion$*</ID>
|
||||
|
@ -391,40 +410,32 @@
|
|||
<ID>MaxLineLength:MainActivity.kt$MainActivity$debug("Asked to open a channel URL - ask user if they want to switch to that channel. If so send the config to the radio")</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$*</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$* Send a mesh packet to the radio, if the radio is not currently connected this function will throw NotConnectedException</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// For the local node, it might not be able to update its times because it doesn't have a valid GPS reading yet</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// If we've received our initial config, our radio settings and all of our channels, send any queued packets and broadcast connected to clients</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// Nodes periodically send out position updates, but those updates might not contain a lat & lon (because no GPS lock)</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// Note: we do not haveNodeDB = true because that means we've got a valid db from a real device (rather than this possibly stale hint)</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// Update last seen for the node that sent the packet, but also for _our node_ because anytime a packet passes</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// Update our last seen based on any valid timestamps. If the device didn't provide a timestamp make one</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// We always start foreground because that's how our service is always started (if we didn't then android would kill us)</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// We like to look at the local node to see if it has been sending out valid lat/lon, so for the LOCAL node (only)</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// We prefer to find nodes based on their assigned IDs, but if no ID has been assigned to a node, we can also find it based on node number</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// because apps really only care about important updates of node state - which handledReceivedData will give them</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// causes the phone to try and reconnect. If we fail downloading our initial radio state we don't want to</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// logAssert(earlyReceivedPackets.size < 128) // The max should normally be about 32, but if the device is messed up it might try to send forever</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$// note: no need to call startDeviceSleep(), because this exception could only have reached us if it was already called</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$/// If we've received our initial config, our radio settings and all of our channels, send any queued packets and broadcast connected to clients</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$/// We prefer to find nodes based on their assigned IDs, but if no ID has been assigned to a node, we can also find it based on node number</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$//logAssert(earlyReceivedPackets.size < 128) // The max should normally be about 32, but if the device is messed up it might try to send forever</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$MeshProtos.FromRadio.MQTTCLIENTPROXYMESSAGE_FIELD_NUMBER -> handleMqttProxyMessage(proto.mqttClientProxyMessage)</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService$debug("Received nodeinfo num=${info.num}, hasUser=${info.hasUser()}, hasPosition=${info.hasPosition()}, hasDeviceMetrics=${info.hasDeviceMetrics()}")</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService.Companion$/// generate a RECEIVED action filter string that includes either the portnumber as an int, or preferably a symbolic name from portnums.proto</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService.Companion.IsUpdatingException$/** We treat software update as similar to loss of comms to the regular bluetooth service (so things like sendPosition for background GPS ignores the problem */</ID>
|
||||
<ID>MaxLineLength:MeshService.kt$MeshService.Companion$// generate a RECEIVED action filter string that includes either the portnumber as an int, or preferably a symbolic name from portnums.proto</ID>
|
||||
<ID>MaxLineLength:MeshServiceBroadcasts.kt$MeshServiceBroadcasts$context.sendBroadcast(intent)</ID>
|
||||
<ID>MaxLineLength:MeshServiceNotifications.kt$MeshServiceNotifications$// If running on really old versions of android (<= 5.1.1) (possibly only cyanogen) we might encounter a bug with setting application specific icons</ID>
|
||||
<ID>MaxLineLength:MessagesFragment.kt$MessagesFragment$button.backgroundTintList = ContextCompat.getColorStateList(requireActivity(), R.color.colorMyMsg)</ID>
|
||||
<ID>MaxLineLength:NodeInfo.kt$MeshUser$return "MeshUser(id=${id.anonymize}, longName=${longName.anonymize}, shortName=${shortName.anonymize}, hwModel=${hwModelString}, isLicensed=${isLicensed})"</ID>
|
||||
<ID>MaxLineLength:NodeInfo.kt$NodeInfo$prefUnits == ConfigProtos.Config.DisplayConfig.DisplayUnits.IMPERIAL_VALUE && dist < 1609 -> "%.0f ft".format(dist.toDouble()*3.281)</ID>
|
||||
<ID>MaxLineLength:NodeInfo.kt$NodeInfo$prefUnits == ConfigProtos.Config.DisplayConfig.DisplayUnits.IMPERIAL_VALUE && dist >= 1609 -> "%.1f mi".format(dist / 1609.34)</ID>
|
||||
<ID>MaxLineLength:NodeInfo.kt$NodeInfo$prefUnits == ConfigProtos.Config.DisplayConfig.DisplayUnits.METRIC_VALUE && dist < 1000 -> "%.0f m".format(dist.toDouble())</ID>
|
||||
<ID>MaxLineLength:NodeInfo.kt$NodeInfo$prefUnits == ConfigProtos.Config.DisplayConfig.DisplayUnits.METRIC_VALUE && dist >= 1000 -> "%.1f km".format(dist / 1000.0)</ID>
|
||||
<ID>MaxLineLength:NodeInfo.kt$Position$/**</ID>
|
||||
<ID>MaxLineLength:NodeInfo.kt$Position$return "Position(lat=${latitude.anonymize}, lon=${longitude.anonymize}, alt=${altitude.anonymize}, time=${time})"</ID>
|
||||
<ID>MaxLineLength:NodeInfoDao.kt$NodeInfoDao$@Query("SELECT * FROM NodeInfo ORDER BY CASE WHEN num = (SELECT myNodeNum FROM MyNodeInfo LIMIT 1) THEN 0 ELSE 1 END, lastHeard DESC")</ID>
|
||||
<ID>MaxLineLength:PositionConfigItemList.kt$.</ID>
|
||||
<ID>MaxLineLength:QuickChatSettingsFragment.kt$QuickChatSettingsFragment$if (builder.modeSwitch.isChecked) QuickChatAction.Mode.Instant else QuickChatAction.Mode.Append</ID>
|
||||
<ID>MaxLineLength:RadioInterfaceService.kt$RadioInterfaceService$/**</ID>
|
||||
<ID>MaxLineLength:RadioInterfaceService.kt$RadioInterfaceService$// If we are running on the emulator we default to the mock interface, so we can have some data to show to the user</ID>
|
||||
<ID>MaxLineLength:RegularPreference.kt$color</ID>
|
||||
<ID>MaxLineLength:RegularPreference.kt$color = if (!enabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) else Color.Unspecified</ID>
|
||||
<ID>MaxLineLength:SafeBluetooth.kt$SafeBluetooth$*</ID>
|
||||
<ID>MaxLineLength:SafeBluetooth.kt$SafeBluetooth$* mtu operations seem to hang sometimes. To cope with this we have a 5 second timeout before throwing an exception and cancelling the work</ID>
|
||||
<ID>MaxLineLength:SafeBluetooth.kt$SafeBluetooth$// Attempt to invoke virtual method 'com.android.bluetooth.gatt.AdvertiseClient com.android.bluetooth.gatt.AdvertiseManager.getAdvertiseClient(int)' on a null object reference</ID>
|
||||
|
@ -452,102 +463,211 @@
|
|||
<ID>MaxLineLength:StreamInterface.kt$StreamInterface$deliverPacket()</ID>
|
||||
<ID>MaxLineLength:StreamInterface.kt$StreamInterface$lostSync()</ID>
|
||||
<ID>MaxLineLength:StreamInterface.kt$StreamInterface$service.onDisconnect(isPermanent = true)</ID>
|
||||
<ID>MaxLineLength:SwitchPreference.kt$color = if (!enabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) else Color.Unspecified</ID>
|
||||
<ID>MaxLineLength:TextDividerPreference.kt$color = if (!enabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) else Color.Unspecified</ID>
|
||||
<ID>MaxLineLength:UIState.kt$UIViewModel$// date,time,from,sender name,sender lat,sender long,rx lat,rx long,rx elevation,rx snr,distance,hop limit,payload</ID>
|
||||
<ID>MaxLineLength:UIState.kt$UIViewModel$writer.appendLine("$rxDateTime,\"$rxFrom\",\"$senderName\",\"$senderLat\",\"$senderLong\",\"$rxLat\",\"$rxLong\",\"$rxAlt\",\"$rxSnr\",\"$dist\",\"$hopLimit\",\"$payload\"")</ID>
|
||||
<ID>MaxLineLength:UIState.kt$UIViewModel$writer.appendLine("\"date\",\"time\",\"from\",\"sender name\",\"sender lat\",\"sender long\",\"rx lat\",\"rx long\",\"rx elevation\",\"rx snr\",\"distance\",\"hop limit\",\"payload\"")</ID>
|
||||
<ID>MayBeConst:AppPrefs.kt$AppPrefs.Companion$private val baseName = "appPrefs_"</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$doDiscoverServicesAndInit()</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$s.asyncDiscoverServices { discRes -> try { discRes.getOrThrow() service.serviceScope.handledLaunch { try { debug("Discovered services!") delay(1000) // android BLE is buggy and needs a 500ms sleep before calling getChracteristic, or you might get back null /* if (isFirstTime) { isFirstTime = false throw BLEException("Faking a BLE failure") } */ fromNum = getCharacteristic(BTM_FROMNUM_CHARACTER) // We treat the first send by a client as special isFirstSend = true // Now tell clients they can (finally use the api) service.onConnect() // Immediately broadcast any queued packets sitting on the device doReadFromRadio(true) } catch (ex: BLEException) { scheduleReconnect( "Unexpected error in initial device enumeration, forcing disconnect $ex" ) } } } catch (ex: BLEException) { if (s.gatt == null) warn("GATT was closed while discovering, assume we are shutting down") else scheduleReconnect( "Unexpected error discovering services, forcing disconnect $ex" ) } }</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$safe?.asyncRequestMtu(512) { mtuRes -> try { mtuRes.getOrThrow() debug("MTU change attempted") // throw BLEException("Test MTU set failed") doDiscoverServicesAndInit() } catch (ex: BLEException) { shouldSetMtu = false scheduleReconnect( "Giving up on setting MTUs, forcing disconnect $ex" ) } }</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$scheduleReconnect( "Unexpected error discovering services, forcing disconnect $ex" )</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$startConnect()</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$startWatchingFromNum()</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$warn("GATT was closed while discovering, assume we are shutting down")</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$warn("Interface is shutting down, so skipping discover")</ID>
|
||||
<ID>MultiLineIfElse:BluetoothInterface.kt$BluetoothInterface$warn("Not connecting, because safe==null, someone must have closed us")</ID>
|
||||
<ID>MultiLineIfElse:BluetoothRepository.kt$BluetoothRepository$bondedDevices.filter { it.name?.matches(Regex(BLE_NAME_PATTERN)) == true }</ID>
|
||||
<ID>MultiLineIfElse:BluetoothRepository.kt$BluetoothRepository$emptyList()</ID>
|
||||
<ID>MultiLineIfElse:BuildUtils.kt$BuildUtils$return Build.SUPPORTED_64_BIT_ABIS.size > 0</ID>
|
||||
<ID>MultiLineIfElse:BuildUtils.kt$BuildUtils$return false</ID>
|
||||
<ID>MultiLineIfElse:Channel.kt$Channel$"Custom"</ID>
|
||||
<ID>MultiLineIfElse:Channel.kt$Channel$when (loraConfig.modemPreset) { ModemPreset.SHORT_TURBO -> "ShortTurbo" ModemPreset.SHORT_FAST -> "ShortFast" ModemPreset.SHORT_SLOW -> "ShortSlow" ModemPreset.MEDIUM_FAST -> "MediumFast" ModemPreset.MEDIUM_SLOW -> "MediumSlow" ModemPreset.LONG_FAST -> "LongFast" ModemPreset.LONG_SLOW -> "LongSlow" ModemPreset.LONG_MODERATE -> "LongMod" ModemPreset.VERY_LONG_SLOW -> "VLongSlow" else -> "Invalid" }</ID>
|
||||
<ID>MultiLineIfElse:ChannelFragment.kt$channelSet = copy { settings.add(it) }</ID>
|
||||
<ID>MultiLineIfElse:ChannelFragment.kt$channelSet = copy { settings[index] = it }</ID>
|
||||
<ID>MultiLineIfElse:ChannelFragment.kt$item { PreferenceFooter( enabled = enabled, onCancelClicked = { focusManager.clearFocus() showChannelEditor = false channelSet = channels }, onSaveClicked = { focusManager.clearFocus() // viewModel.setRequestChannelUrl(channelUrl) sendButton() }) }</ID>
|
||||
<ID>MultiLineIfElse:ChannelOption.kt$when (bandwidth) { 31 -> .03125f 62 -> .0625f 200 -> .203125f 400 -> .40625f 800 -> .8125f 1600 -> 1.6250f else -> bandwidth / 1000f }</ID>
|
||||
<ID>MultiLineIfElse:ContextServices.kt$MaterialAlertDialogBuilder(this) .setTitle(title) .setMessage(rationale) .setNeutralButton(R.string.cancel) { _, _ -> } .setPositiveButton(R.string.accept) { _, _ -> invokeFun() } .show()</ID>
|
||||
<ID>MultiLineIfElse:ContextServices.kt$invokeFun()</ID>
|
||||
<ID>MultiLineIfElse:DeviceSettingsFragment.kt$AlertDialog( onDismissRequest = {}, shape = RoundedCornerShape(16.dp), backgroundColor = MaterialTheme.colors.background, title = { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center, ) { Icon( imageVector = Icons.TwoTone.Warning, contentDescription = "warning", modifier = Modifier.padding(end = 8.dp) ) Text( text = "${stringResource(title)}?\n") Icon( imageVector = Icons.TwoTone.Warning, contentDescription = "warning", modifier = Modifier.padding(start = 8.dp) ) } }, buttons = { Row( modifier = Modifier .fillMaxWidth() .padding(start = 16.dp, end = 16.dp, bottom = 16.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { TextButton( modifier = Modifier.weight(1f), onClick = { showDialog = false }, ) { Text(stringResource(R.string.cancel)) } Button( modifier = Modifier.weight(1f), onClick = { showDialog = false onClick() }, ) { Text(stringResource(R.string.send)) } } } )</ID>
|
||||
<ID>MultiLineIfElse:DeviceSettingsFragment.kt$EditDeviceProfileDialog( title = if (deviceProfile != null) "Import configuration" else "Export configuration", deviceProfile = deviceProfile ?: viewModel.currentDeviceProfile, onConfirm = { showEditDeviceProfileDialog = false if (deviceProfile != null) { viewModel.installProfile(it) } else { viewModel.setDeviceProfile(it) val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "application/*" putExtra(Intent.EXTRA_TITLE, "${destNum.toUInt()}.cfg") } exportConfigLauncher.launch(intent) } }, onDismiss = { showEditDeviceProfileDialog = false viewModel.setDeviceProfile(null) } )</ID>
|
||||
<ID>MultiLineIfElse:DeviceSettingsFragment.kt$PacketResponseStateDialog( radioConfigState.responseState, onDismiss = { showEditDeviceProfileDialog = false viewModel.clearPacketResponse() }, onComplete = { val route = radioConfigState.route if (ConfigRoute.entries.any { it.name == route } || ModuleRoute.entries.any { it.name == route }) { navController.navigate(route) viewModel.clearPacketResponse() } } )</ID>
|
||||
<ID>MultiLineIfElse:EditListPreference.kt$EditBase64Preference( title = "${index + 1}/$maxCount", value = value, enabled = enabled, keyboardActions = keyboardActions, onValueChange = { listState[index] = it as T onValuesChanged(listState) }, modifier = modifier.fillMaxWidth(), trailingIcon = trailingIcon, )</ID>
|
||||
<ID>MultiLineIfElse:EditListPreference.kt$EditTextPreference( title = "${index + 1}/$maxCount", value = value, enabled = enabled, keyboardActions = keyboardActions, onValueChanged = { listState[index] = it as T onValuesChanged(listState) }, modifier = modifier.fillMaxWidth(), trailingIcon = trailingIcon, )</ID>
|
||||
<ID>MultiLineIfElse:EditPasswordPreference.kt$painterResource(R.drawable.ic_twotone_visibility_24)</ID>
|
||||
<ID>MultiLineIfElse:EditPasswordPreference.kt$painterResource(R.drawable.ic_twotone_visibility_off_24)</ID>
|
||||
<ID>MultiLineIfElse:EditTextPreference.kt$it.toDoubleOrNull()?.let { double -> valueState = it onValueChanged(double) }</ID>
|
||||
<ID>MultiLineIfElse:EditTextPreference.kt$it.toFloatOrNull()?.let { float -> valueState = it onValueChanged(float) }</ID>
|
||||
<ID>MultiLineIfElse:EditTextPreference.kt$it.toUIntOrNull()?.toInt()?.let { int -> valueState = it onValueChanged(int) }</ID>
|
||||
<ID>MultiLineIfElse:EditTextPreference.kt$onValueChanged(it)</ID>
|
||||
<ID>MultiLineIfElse:EditTextPreference.kt$valueState = it</ID>
|
||||
<ID>MultiLineIfElse:EditWaypointDialog.kt$AlertDialog( onDismissRequest = onDismissRequest, shape = RoundedCornerShape(16.dp), backgroundColor = MaterialTheme.colors.background, text = { Column(modifier = modifier.fillMaxWidth()) { Text( text = stringResource(title), style = MaterialTheme.typography.h6.copy( fontWeight = FontWeight.Bold, textAlign = TextAlign.Center, ), modifier = Modifier .fillMaxWidth() .padding(bottom = 16.dp), ) EditTextPreference( title = stringResource(R.string.name), value = waypointInput.name, maxSize = 29, // name max_size:30 enabled = true, isError = false, keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Text, imeAction = ImeAction.Done ), keyboardActions = KeyboardActions(onDone = { /*TODO*/ }), onValueChanged = { waypointInput = waypointInput.copy { name = it } }, trailingIcon = { IconButton(onClick = { showEmojiPickerView = true }) { Text( text = String(Character.toChars(emoji)), modifier = Modifier .background(MaterialTheme.colors.background, CircleShape) .padding(4.dp), fontSize = 24.sp, color = Color.Unspecified.copy(alpha = 1f), ) } }, ) EditTextPreference(title = stringResource(R.string.description), value = waypointInput.description, maxSize = 99, // description max_size:100 enabled = true, isError = false, keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Text, imeAction = ImeAction.Done ), keyboardActions = KeyboardActions(onDone = { /*TODO*/ }), onValueChanged = { waypointInput = waypointInput.copy { description = it } } ) Row( modifier = Modifier .fillMaxWidth() .size(48.dp), verticalAlignment = Alignment.CenterVertically ) { Image( painter = painterResource(R.drawable.ic_twotone_lock_24), contentDescription = stringResource(R.string.locked), ) Text(stringResource(R.string.locked)) Switch( modifier = Modifier .fillMaxWidth() .wrapContentWidth(Alignment.End), checked = waypointInput.lockedTo != 0, onCheckedChange = { waypointInput = waypointInput.copy { lockedTo = if (it) 1 else 0 } } ) } } }, buttons = { FlowRow( modifier = modifier.padding(start = 20.dp, end = 20.dp, bottom = 16.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.Center, ) { TextButton( modifier = modifier.weight(1f), onClick = onDismissRequest ) { Text(stringResource(R.string.cancel)) } if (waypoint.id != 0) { Button( modifier = modifier.weight(1f), onClick = { onDeleteClicked(waypointInput) }, enabled = waypointInput.name.isNotEmpty(), ) { Text(stringResource(R.string.delete)) } } Button( modifier = modifier.weight(1f), onClick = { onSendClicked(waypointInput) }, enabled = waypointInput.name.isNotEmpty(), ) { Text(stringResource(R.string.send)) } } }, )</ID>
|
||||
<ID>MultiLineIfElse:Exceptions.kt$Exceptions.errormsg("ignoring exception", ex)</ID>
|
||||
<ID>MultiLineIfElse:ExpireChecker.kt$ExpireChecker$doExpire()</ID>
|
||||
<ID>MultiLineIfElse:ExternalNotificationConfigItemList.kt$item { SwitchPreference(title = "Output LED active high", checked = externalNotificationInput.active, enabled = enabled, onCheckedChange = { externalNotificationInput = externalNotificationInput.copy { active = it } }) }</ID>
|
||||
<ID>MultiLineIfElse:ExternalNotificationConfigItemList.kt$item { SwitchPreference(title = "Use PWM buzzer", checked = externalNotificationInput.usePwm, enabled = enabled, onCheckedChange = { externalNotificationInput = externalNotificationInput.copy { usePwm = it } }) }</ID>
|
||||
<ID>MultiLineIfElse:Logging.kt$Logging$printlog(Log.ERROR, tag(), "$msg (exception ${ex.message})")</ID>
|
||||
<ID>MultiLineIfElse:Logging.kt$Logging$printlog(Log.ERROR, tag(), "$msg")</ID>
|
||||
<ID>MultiLineIfElse:MapFragment.kt$<no name provided>$showEditWaypointDialog = waypoint { latitudeI = (p.latitude * 1e7).toInt() longitudeI = (p.longitude * 1e7).toInt() }</ID>
|
||||
<ID>MultiLineIfElse:MapFragment.kt$CacheLayout( cacheEstimate = cacheEstimate, onExecuteJob = { startDownload() }, onCancelDownload = { downloadRegionBoundingBox = null map.overlays.removeAll { it is Polygon } map.invalidate() }, modifier = Modifier.align(Alignment.BottomCenter) )</ID>
|
||||
<ID>MultiLineIfElse:MapFragment.kt$Column( modifier = Modifier .padding(top = 16.dp, end = 16.dp) .align(Alignment.TopEnd), verticalArrangement = Arrangement.spacedBy(8.dp), ) { MapButton( onClick = { showMapStyleDialog() }, drawableRes = R.drawable.ic_twotone_layers_24, contentDescription = R.string.map_style_selection, ) MapButton( onClick = { if (context.hasLocationPermission()) { map.toggleMyLocation() } else { requestPermissionAndToggleLauncher.launch(context.getLocationPermissions()) } }, enabled = hasGps, drawableRes = if (myLocationOverlay == null) { R.drawable.ic_twotone_my_location_24 } else { R.drawable.ic_twotone_location_disabled_24 }, contentDescription = null, ) }</ID>
|
||||
<ID>MultiLineIfElse:MapViewWithLifecycle.kt$try { acquire() } catch (e: SecurityException) { errormsg("WakeLock permission exception: ${e.message}") } catch (e: IllegalStateException) { errormsg("WakeLock acquire() exception: ${e.message}") }</ID>
|
||||
<ID>MultiLineIfElse:MapViewWithLifecycle.kt$try { release() } catch (e: IllegalStateException) { errormsg("WakeLock release() exception: ${e.message}") }</ID>
|
||||
<ID>MultiLineIfElse:MeshService.kt$MeshService$getDataPacketById(packetId)?.let { p -> if (p.status == m) return@handledLaunch packetRepository.get().updateMessageStatus(p, m) serviceBroadcasts.broadcastMessageStatus(packetId, m) }</ID>
|
||||
<ID>MultiLineIfElse:MeshService.kt$MeshService$p</ID>
|
||||
<ID>MultiLineIfElse:MeshService.kt$MeshService$p.copy { warn("Public key mismatch from $longName ($shortName)") publicKey = it.errorByteString }</ID>
|
||||
<ID>MultiLineIfElse:MeshService.kt$MeshService.<no name provided>$try { sendNow(p) } catch (ex: Exception) { errormsg("Error sending message, so enqueueing", ex) enqueueForSending(p) }</ID>
|
||||
<ID>MultiLineIfElse:NOAAWmsTileSource.kt$NOAAWmsTileSource$sb.append("service=WMS")</ID>
|
||||
<ID>MultiLineIfElse:NodeInfo.kt$MeshUser$hwModel.name.replace('_', '-').replace('p', '.').lowercase()</ID>
|
||||
<ID>MultiLineIfElse:NodeInfo.kt$MeshUser$null</ID>
|
||||
<ID>MultiLineIfElse:RadioConfigViewModel.kt$RadioConfigViewModel$destNode.value?.user?.let { val user = MeshProtos.User.newBuilder() .setLongName(if (hasLongName()) longName else it.longName) .setShortName(if (hasShortName()) shortName else it.shortName) .setIsLicensed(it.isLicensed) .build() setOwner(user) }</ID>
|
||||
<ID>MultiLineIfElse:RadioConfigViewModel.kt$RadioConfigViewModel$try { setChannels(channelUrl) } catch (ex: Exception) { errormsg("DeviceProfile channel import error", ex) setResponseStateError(ex.customMessage) }</ID>
|
||||
<ID>MultiLineIfElse:RadioConfigViewModel.kt$RadioConfigViewModel$viewModelScope.launch { radioConfigRepository.replaceAllSettings(new) }</ID>
|
||||
<ID>MultiLineIfElse:RadioInterfaceService.kt$RadioInterfaceService$startInterface()</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$cb</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$null</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$startNewWork()</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$throw AssertionError("currentWork was not null: $currentWork")</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$warn("wor completed, but we already killed it via failsafetimer? status=$status, res=$res")</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$work.completion.resume(Result.success(res) as Result<Nothing>)</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$work.completion.resumeWithException( BLEStatusException( status, "Bluetooth status=$status while doing ${work.tag}" ) )</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.<no name provided>$completeWork(status, Unit)</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.<no name provided>$completeWork(status, characteristic)</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.<no name provided>$dropAndReconnect()</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.<no name provided>$errormsg("Ignoring bogus onMtuChanged")</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.<no name provided>$if (!characteristic.value.contentEquals(reliable)) { errormsg("A reliable write failed!") gatt.abortReliableWrite() completeWork( STATUS_RELIABLE_WRITE_FAILED, characteristic ) // skanky code to indicate failure } else { logAssert(gatt.executeReliableWrite()) // After this execute reliable completes - we can continue with normal operations (see onReliableWriteCompleted) }</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.<no name provided>$lostConnection("lost connection")</ID>
|
||||
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.<no name provided>$warn("Received notification from $characteristic, but no handler registered")</ID>
|
||||
<ID>MultiLineIfElse:TextDividerPreference.kt$Icon( trailingIcon, "trailingIcon", modifier = modifier .fillMaxWidth() .wrapContentWidth(Alignment.End), )</ID>
|
||||
<ID>MultiLineIfElse:UIState.kt$add(channel { role = when (i) { 0 -> ChannelProtos.Channel.Role.PRIMARY in 1..new.lastIndex -> ChannelProtos.Channel.Role.SECONDARY else -> ChannelProtos.Channel.Role.DISABLED } index = i settings = new.getOrNull(i) ?: channelSettings { } })</ID>
|
||||
<ID>NestedBlockDepth:LanguageUtils.kt$LanguageUtils$fun getLanguageTags(context: Context): Map<String, String></ID>
|
||||
<ID>NestedBlockDepth:MainActivity.kt$MainActivity$private fun onMeshConnectionChanged(newConnection: MeshService.ConnectionState)</ID>
|
||||
<ID>NestedBlockDepth:MeshService.kt$MeshService$private fun handleReceivedAdmin(fromNodeNum: Int, a: AdminProtos.AdminMessage)</ID>
|
||||
<ID>NestedBlockDepth:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)</ID>
|
||||
<ID>NestedBlockDepth:RadioConfigViewModel.kt$RadioConfigViewModel$fun installProfile(protobuf: DeviceProfile)</ID>
|
||||
<ID>NestedBlockDepth:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)</ID>
|
||||
<ID>NewLineAtEndOfFile:AppIntroduction.kt$com.geeksville.mesh.AppIntroduction.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:AppPrefs.kt$com.geeksville.mesh.android.AppPrefs.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:ApplicationModule.kt$com.geeksville.mesh.ApplicationModule.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:BLEException.kt$com.geeksville.mesh.service.BLEException.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:BluetoothInterfaceFactory.kt$com.geeksville.mesh.repository.radio.BluetoothInterfaceFactory.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:BluetoothInterfaceSpec.kt$com.geeksville.mesh.repository.radio.BluetoothInterfaceSpec.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:BluetoothRepositoryModule.kt$com.geeksville.mesh.repository.bluetooth.BluetoothRepositoryModule.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:BluetoothViewModel.kt$com.geeksville.mesh.model.BluetoothViewModel.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:BootCompleteReceiver.kt$com.geeksville.mesh.service.BootCompleteReceiver.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:Color.kt$com.geeksville.mesh.ui.theme.Color.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:ContactsViewModel.kt$com.geeksville.mesh.model.ContactsViewModel.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:CoroutineDispatchers.kt$com.geeksville.mesh.CoroutineDispatchers.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:Coroutines.kt$com.geeksville.mesh.concurrent.Coroutines.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:CustomTileSource.kt$com.geeksville.mesh.model.map.CustomTileSource.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DataPacket.kt$com.geeksville.mesh.DataPacket.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DatabaseModule.kt$com.geeksville.mesh.database.DatabaseModule.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DateUtils.kt$com.geeksville.mesh.android.DateUtils.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DebugLogFile.kt$com.geeksville.mesh.android.DebugLogFile.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DeferredExecution.kt$com.geeksville.mesh.concurrent.DeferredExecution.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DeviceVersion.kt$com.geeksville.mesh.model.DeviceVersion.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DeviceVersionTest.kt$com.geeksville.mesh.model.DeviceVersionTest.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DistanceExtensions.kt$com.geeksville.mesh.util.DistanceExtensions.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:DragManageAdapter.kt$com.geeksville.mesh.ui.DragManageAdapter.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:ElevationInfo.kt$com.geeksville.mesh.ui.compose.ElevationInfo.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:ExpireChecker.kt$com.geeksville.mesh.android.ExpireChecker.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:InterfaceFactory.kt$com.geeksville.mesh.repository.radio.InterfaceFactory.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:InterfaceFactorySpi.kt$com.geeksville.mesh.repository.radio.InterfaceFactorySpi.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:InterfaceId.kt$com.geeksville.mesh.repository.radio.InterfaceId.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:InterfaceSpec.kt$com.geeksville.mesh.repository.radio.InterfaceSpec.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:LanguageUtils.kt$com.geeksville.mesh.util.LanguageUtils.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:LastHeardInfo.kt$com.geeksville.mesh.ui.LastHeardInfo.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:LinkedCoordinates.kt$com.geeksville.mesh.ui.LinkedCoordinates.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:Logging.kt$com.geeksville.mesh.android.Logging.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:MeshLogDao.kt$com.geeksville.mesh.database.dao.MeshLogDao.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:MeshLogRepository.kt$com.geeksville.mesh.database.MeshLogRepository.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:MockInterfaceFactory.kt$com.geeksville.mesh.repository.radio.MockInterfaceFactory.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:MockInterfaceSpec.kt$com.geeksville.mesh.repository.radio.MockInterfaceSpec.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:NOAAWmsTileSource.kt$com.geeksville.mesh.model.map.NOAAWmsTileSource.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:NodeFilterTextField.kt$com.geeksville.mesh.ui.components.NodeFilterTextField.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:NopInterface.kt$com.geeksville.mesh.repository.radio.NopInterface.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:NopInterfaceFactory.kt$com.geeksville.mesh.repository.radio.NopInterfaceFactory.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:NopInterfaceSpec.kt$com.geeksville.mesh.repository.radio.NopInterfaceSpec.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:OnlineTileSourceAuth.kt$com.geeksville.mesh.model.map.OnlineTileSourceAuth.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:PreferenceCategory.kt$com.geeksville.mesh.ui.components.PreferenceCategory.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:PreviewParameterProviders.kt$com.geeksville.mesh.ui.preview.PreviewParameterProviders.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:ProbeTableProvider.kt$com.geeksville.mesh.repository.usb.ProbeTableProvider.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:QuickChatAction.kt$com.geeksville.mesh.database.entity.QuickChatAction.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:QuickChatActionAdapter.kt$com.geeksville.mesh.ui.QuickChatActionAdapter.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:QuickChatActionDao.kt$com.geeksville.mesh.database.dao.QuickChatActionDao.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:QuickChatActionRepository.kt$com.geeksville.mesh.database.QuickChatActionRepository.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:QuickChatSettingsFragment.kt$com.geeksville.mesh.ui.QuickChatSettingsFragment.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:RadioNotConnectedException.kt$com.geeksville.mesh.service.RadioNotConnectedException.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:RadioRepositoryModule.kt$com.geeksville.mesh.repository.radio.RadioRepositoryModule.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:RegularPreference.kt$com.geeksville.mesh.ui.components.RegularPreference.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SafeBluetooth.kt$com.geeksville.mesh.service.SafeBluetooth.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SatelliteCountInfo.kt$com.geeksville.mesh.ui.compose.SatelliteCountInfo.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SerialConnection.kt$com.geeksville.mesh.repository.usb.SerialConnection.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SerialConnectionImpl.kt$com.geeksville.mesh.repository.usb.SerialConnectionImpl.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SerialConnectionListener.kt$com.geeksville.mesh.repository.usb.SerialConnectionListener.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SerialInterface.kt$com.geeksville.mesh.repository.radio.SerialInterface.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SerialInterfaceFactory.kt$com.geeksville.mesh.repository.radio.SerialInterfaceFactory.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SerialInterfaceSpec.kt$com.geeksville.mesh.repository.radio.SerialInterfaceSpec.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:ServiceClient.kt$com.geeksville.mesh.android.ServiceClient.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SoftwareUpdateService.kt$com.geeksville.mesh.service.SoftwareUpdateService.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:SqlTileWriterExt.kt$com.geeksville.mesh.util.SqlTileWriterExt.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:StreamInterface.kt$com.geeksville.mesh.repository.radio.StreamInterface.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:TCPInterfaceFactory.kt$com.geeksville.mesh.repository.radio.TCPInterfaceFactory.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:TCPInterfaceSpec.kt$com.geeksville.mesh.repository.radio.TCPInterfaceSpec.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:Theme.kt$com.geeksville.mesh.ui.theme.Theme.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:UsbBroadcastReceiver.kt$com.geeksville.mesh.repository.usb.UsbBroadcastReceiver.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:UsbRepository.kt$com.geeksville.mesh.repository.usb.UsbRepository.kt</ID>
|
||||
<ID>NewLineAtEndOfFile:UsbRepositoryModule.kt$com.geeksville.mesh.repository.usb.UsbRepositoryModule.kt</ID>
|
||||
<ID>NoBlankLineBeforeRbrace:BluetoothInterface.kt$BluetoothInterface$ </ID>
|
||||
<ID>NoBlankLineBeforeRbrace:CustomTileSource.kt$CustomTileSource$ </ID>
|
||||
<ID>NoBlankLineBeforeRbrace:DebugLogFile.kt$BinaryLogFile$ </ID>
|
||||
<ID>NoBlankLineBeforeRbrace:NOAAWmsTileSource.kt$NOAAWmsTileSource$ </ID>
|
||||
<ID>NoBlankLineBeforeRbrace:NopInterface.kt$NopInterface$ </ID>
|
||||
<ID>NoBlankLineBeforeRbrace:OnlineTileSourceAuth.kt$OnlineTileSourceAuth$ </ID>
|
||||
<ID>NoBlankLineBeforeRbrace:PositionTest.kt$PositionTest$ </ID>
|
||||
<ID>NoBlankLineBeforeRbrace:PreviewParameterProviders.kt$NodeInfoPreviewParameterProvider$ </ID>
|
||||
<ID>NoBlankLineBeforeRbrace:QuickChatActionDao.kt$QuickChatActionDao$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:AppIntroduction.kt$AppIntroduction$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:AppPrefs.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:BluetoothInterface.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:BluetoothInterface.kt$BluetoothInterface$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:BootCompleteReceiver.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:CommonCharts.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:Constants.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:CustomTileSource.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:CustomTileSource.kt$CustomTileSource.Companion$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:DebugLogFile.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:DeferredExecution.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:EnvironmentMetrics.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:Exceptions.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:IRadioInterface.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:NOAAWmsTileSource.kt$NOAAWmsTileSource$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:NodeInfo.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:PositionTest.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:PreviewParameterProviders.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:SafeBluetooth.kt$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:SafeBluetooth.kt$SafeBluetooth$ </ID>
|
||||
<ID>NoConsecutiveBlankLines:SqlTileWriterExt.kt$ </ID>
|
||||
<ID>NoEmptyClassBody:DebugLogFile.kt$BinaryLogFile${ }</ID>
|
||||
<ID>NoSemicolons:DateUtils.kt$DateUtils$;</ID>
|
||||
<ID>NoTrailingSpaces:ExpireChecker.kt$ExpireChecker$ </ID>
|
||||
<ID>NoWildcardImports:BluetoothInterface.kt$import com.geeksville.mesh.service.*</ID>
|
||||
<ID>NoWildcardImports:DeviceVersionTest.kt$import org.junit.Assert.*</ID>
|
||||
<ID>NoWildcardImports:ExampleUnitTest.kt$import org.junit.Assert.*</ID>
|
||||
<ID>NoWildcardImports:MainActivity.kt$import android.content.*</ID>
|
||||
<ID>NoWildcardImports:MainActivity.kt$import com.geeksville.mesh.android.*</ID>
|
||||
<ID>NoWildcardImports:MainActivity.kt$import com.geeksville.mesh.service.*</ID>
|
||||
<ID>NoWildcardImports:MainActivity.kt$import com.geeksville.mesh.ui.*</ID>
|
||||
<ID>NoWildcardImports:MeshService.kt$import com.geeksville.mesh.*</ID>
|
||||
<ID>NoWildcardImports:MeshService.kt$import com.geeksville.mesh.util.*</ID>
|
||||
<ID>NoWildcardImports:MockInterface.kt$import com.geeksville.mesh.*</ID>
|
||||
<ID>NoWildcardImports:PreferenceFooter.kt$import androidx.compose.foundation.layout.*</ID>
|
||||
<ID>NoWildcardImports:PreferenceFooter.kt$import androidx.compose.material.*</ID>
|
||||
<ID>NoWildcardImports:QuickChatActionDao.kt$import androidx.room.*</ID>
|
||||
<ID>NoWildcardImports:SafeBluetooth.kt$import android.bluetooth.*</ID>
|
||||
<ID>NoWildcardImports:SafeBluetooth.kt$import kotlinx.coroutines.*</ID>
|
||||
<ID>NoWildcardImports:SettingsFragment.kt$import com.geeksville.mesh.android.*</ID>
|
||||
<ID>NoWildcardImports:UIState.kt$import com.geeksville.mesh.*</ID>
|
||||
<ID>NoWildcardImports:UsbRepository.kt$import kotlinx.coroutines.flow.*</ID>
|
||||
<ID>OptionalAbstractKeyword:SyncContinuation.kt$Continuation$abstract</ID>
|
||||
<ID>ParameterListWrapping:AppPrefs.kt$FloatPref$(thisRef: AppPrefs, prop: KProperty<Float>)</ID>
|
||||
<ID>ParameterListWrapping:AppPrefs.kt$StringPref$(thisRef: AppPrefs, prop: KProperty<String>)</ID>
|
||||
<ID>ParameterListWrapping:SafeBluetooth.kt$SafeBluetooth$( c: BluetoothGattCharacteristic, cont: Continuation<BluetoothGattCharacteristic>, timeout: Long = 0 )</ID>
|
||||
<ID>ParameterListWrapping:SafeBluetooth.kt$SafeBluetooth$( c: BluetoothGattCharacteristic, cont: Continuation<Unit>, timeout: Long = 0 )</ID>
|
||||
<ID>ParameterListWrapping:SafeBluetooth.kt$SafeBluetooth$( c: BluetoothGattCharacteristic, v: ByteArray, cont: Continuation<BluetoothGattCharacteristic>, timeout: Long = 0 )</ID>
|
||||
<ID>ParameterListWrapping:SafeBluetooth.kt$SafeBluetooth$( c: BluetoothGattDescriptor, cont: Continuation<BluetoothGattDescriptor>, timeout: Long = 0 )</ID>
|
||||
<ID>RethrowCaughtException:SyncContinuation.kt$Continuation$throw ex</ID>
|
||||
<ID>ReturnCount:ChannelOption.kt$internal fun LoRaConfig.radioFreq(channelNum: Int): Float</ID>
|
||||
<ID>ReturnCount:Extensions.kt$fun formatAgo(lastSeenUnix: Int): String</ID>
|
||||
<ID>ReturnCount:MainActivity.kt$MainActivity$override fun onOptionsItemSelected(item: MenuItem): Boolean</ID>
|
||||
<ID>ReturnCount:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket)</ID>
|
||||
<ID>ReturnCount:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)</ID>
|
||||
<ID>SpacingAroundColon:PreviewParameterProviders.kt$NodeInfoPreviewParameterProvider$:</ID>
|
||||
<ID>SpacingAroundCurly:AppPrefs.kt$FloatPref$}</ID>
|
||||
<ID>SpacingAroundKeyword:AppPrefs.kt$AppPrefs$if</ID>
|
||||
<ID>SpacingAroundKeyword:Exceptions.kt$if</ID>
|
||||
<ID>SpacingAroundKeyword:Exceptions.kt$when</ID>
|
||||
<ID>SpacingAroundOperators:NodeInfo.kt$NodeInfo$*</ID>
|
||||
<ID>SpacingAroundRangeOperator:BatteryInfo.kt$..</ID>
|
||||
<ID>StringTemplate:NodeInfo.kt$Position$${time}</ID>
|
||||
<ID>SwallowedException:BluetoothInterface.kt$BluetoothInterface$ex: CancellationException</ID>
|
||||
<ID>SwallowedException:ChannelFragment.kt$ex: Throwable</ID>
|
||||
<ID>SwallowedException:ChannelSet.kt$ex: Throwable</ID>
|
||||
<ID>SwallowedException:DeviceVersion.kt$DeviceVersion$e: Exception</ID>
|
||||
<ID>SwallowedException:EditChannelDialog.kt$ex: Throwable</ID>
|
||||
<ID>SwallowedException:Exceptions.kt$ex: Throwable</ID>
|
||||
<ID>SwallowedException:MainActivity.kt$MainActivity$ex: BindFailedException</ID>
|
||||
<ID>SwallowedException:MainActivity.kt$MainActivity$ex: IllegalStateException</ID>
|
||||
|
@ -562,14 +682,12 @@
|
|||
<ID>SwallowedException:SafeBluetooth.kt$SafeBluetooth$ex: NullPointerException</ID>
|
||||
<ID>SwallowedException:ServiceClient.kt$ServiceClient$ex: IllegalArgumentException</ID>
|
||||
<ID>SwallowedException:TCPInterface.kt$TCPInterface$ex: SocketTimeoutException</ID>
|
||||
<ID>ThrowsCount:MeshService.kt$MeshService$private fun doFirmwareUpdate()</ID>
|
||||
<ID>TooGenericExceptionCaught:BTScanModel.kt$BTScanModel$ex: Throwable</ID>
|
||||
<ID>TooGenericExceptionCaught:BluetoothInterface.kt$BluetoothInterface$ex: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:ChannelFragment.kt$ex: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:ChannelFragment.kt$ex: Throwable</ID>
|
||||
<ID>TooGenericExceptionCaught:ChannelSet.kt$ex: Throwable</ID>
|
||||
<ID>TooGenericExceptionCaught:DeviceVersion.kt$DeviceVersion$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:EditChannelDialog.kt$ex: Throwable</ID>
|
||||
<ID>TooGenericExceptionCaught:Exceptions.kt$ex: Throwable</ID>
|
||||
<ID>TooGenericExceptionCaught:LanguageUtils.kt$LanguageUtils$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:LocationRepository.kt$LocationRepository$e: Exception</ID>
|
||||
|
@ -589,23 +707,18 @@
|
|||
<ID>TooGenericExceptionCaught:TCPInterface.kt$TCPInterface$ex: Throwable</ID>
|
||||
<ID>TooGenericExceptionThrown:DeviceVersion.kt$DeviceVersion$throw Exception("Can't parse version $s")</ID>
|
||||
<ID>TooGenericExceptionThrown:MeshService.kt$MeshService$throw Exception("Can't set user without a NodeInfo")</ID>
|
||||
<ID>TooGenericExceptionThrown:MeshService.kt$MeshService$throw Exception("Can't update - no bluetooth connected")</ID>
|
||||
<ID>TooGenericExceptionThrown:MeshService.kt$MeshService$throw Exception("Firmware update already running")</ID>
|
||||
<ID>TooGenericExceptionThrown:MeshService.kt$MeshService$throw Exception("No update filename")</ID>
|
||||
<ID>TooGenericExceptionThrown:MeshService.kt$MeshService.<no name provided>$throw Exception("Port numbers must be non-zero!")</ID>
|
||||
<ID>TooGenericExceptionThrown:ServiceClient.kt$ServiceClient$throw Exception("Haven't called connect")</ID>
|
||||
<ID>TooGenericExceptionThrown:ServiceClient.kt$ServiceClient$throw Exception("Service not bound")</ID>
|
||||
<ID>TooGenericExceptionThrown:SyncContinuation.kt$SyncContinuation$throw Exception("SyncContinuation timeout")</ID>
|
||||
<ID>TooGenericExceptionThrown:SyncContinuation.kt$SyncContinuation$throw Exception("This shouldn't happen")</ID>
|
||||
<ID>TooManyFunctions:AppPrefs.kt$AppPrefs</ID>
|
||||
<ID>TooManyFunctions:BTScanModel.kt$BTScanModel : ViewModelLogging</ID>
|
||||
<ID>TooManyFunctions:BluetoothInterface.kt$BluetoothInterface : IRadioInterfaceLogging</ID>
|
||||
<ID>TooManyFunctions:ContextServices.kt$com.geeksville.mesh.android.ContextServices.kt</ID>
|
||||
<ID>TooManyFunctions:LocationUtils.kt$com.geeksville.mesh.util.LocationUtils.kt</ID>
|
||||
<ID>TooManyFunctions:MainActivity.kt$MainActivity : AppCompatActivityLogging</ID>
|
||||
<ID>TooManyFunctions:MeshService.kt$MeshService : ServiceLogging</ID>
|
||||
<ID>TooManyFunctions:MeshService.kt$MeshService$<no name provided> : Stub</ID>
|
||||
<ID>TooManyFunctions:ModuleConfigRepository.kt$ModuleConfigRepository : Logging</ID>
|
||||
<ID>TooManyFunctions:PacketDao.kt$PacketDao</ID>
|
||||
<ID>TooManyFunctions:PacketRepository.kt$PacketRepository</ID>
|
||||
<ID>TooManyFunctions:RadioConfigRepository.kt$RadioConfigRepository</ID>
|
||||
|
@ -614,19 +727,7 @@
|
|||
<ID>TooManyFunctions:SafeBluetooth.kt$SafeBluetooth : LoggingCloseable</ID>
|
||||
<ID>TooManyFunctions:SettingsFragment.kt$SettingsFragment : ScreenFragmentLogging</ID>
|
||||
<ID>TooManyFunctions:UIState.kt$UIViewModel : ViewModelLogging</ID>
|
||||
<ID>TopLevelPropertyNaming:ChannelSet.kt$internal const val URL_PREFIX = "https://meshtastic.org/e/#"</ID>
|
||||
<ID>TopLevelPropertyNaming:Constants.kt$// a bool true means now connected, false means not const val EXTRA_CONNECTED = "$prefix.Connected"</ID>
|
||||
<ID>TopLevelPropertyNaming:Constants.kt$/// a bool true means we expect this condition to continue until, false means device might come back const val EXTRA_PERMANENT = "$prefix.Permanent"</ID>
|
||||
<ID>TopLevelPropertyNaming:Constants.kt$const val EXTRA_NODEINFO = "$prefix.NodeInfo"</ID>
|
||||
<ID>TopLevelPropertyNaming:Constants.kt$const val EXTRA_PACKET_ID = "$prefix.PacketId"</ID>
|
||||
<ID>TopLevelPropertyNaming:Constants.kt$const val EXTRA_PAYLOAD = "$prefix.Payload"</ID>
|
||||
<ID>TopLevelPropertyNaming:Constants.kt$const val EXTRA_PROGRESS = "$prefix.Progress"</ID>
|
||||
<ID>TopLevelPropertyNaming:Constants.kt$const val EXTRA_STATUS = "$prefix.Status"</ID>
|
||||
<ID>TopLevelPropertyNaming:Constants.kt$const val prefix = "com.geeksville.mesh"</ID>
|
||||
<ID>TopLevelPropertyNaming:UsbManager.kt$private const val ACTION_USB_PERMISSION = "com.geeksville.mesh.USB_PERMISSION"</ID>
|
||||
<ID>UnusedParameter:PositionPrecisionPreference.kt$modifier: Modifier = Modifier</ID>
|
||||
<ID>UnusedPrivateMember:MeshService.kt$MeshService$private fun processQueuedPackets()</ID>
|
||||
<ID>UnusedPrivateMember:MeshService.kt$MeshService$private fun requestAllConfig()</ID>
|
||||
<ID>UnusedPrivateMember:NOAAWmsTileSource.kt$NOAAWmsTileSource$private fun tile2lat(y: Int, z: Int): Double</ID>
|
||||
<ID>UnusedPrivateMember:NOAAWmsTileSource.kt$NOAAWmsTileSource$private fun tile2lon(x: Int, z: Int): Double</ID>
|
||||
<ID>UnusedPrivateMember:SafeBluetooth.kt$SafeBluetooth$private fun reconnect()</ID>
|
||||
|
@ -635,8 +736,6 @@
|
|||
<ID>UnusedPrivateProperty:CustomTileSource.kt$CustomTileSource.Companion$private val SEAMAP: OnlineTileSourceBase = TileSourceFactory.OPEN_SEAMAP</ID>
|
||||
<ID>UnusedPrivateProperty:CustomTileSource.kt$CustomTileSource.Companion$private val USGS_HYDRO_CACHE = object : OnlineTileSourceBase( "USGS Hydro Cache", 0, 18, 256, "", arrayOf( "https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/tile/" ), "USGS", TileSourcePolicy( 2, TileSourcePolicy.FLAG_NO_PREVENTIVE or TileSourcePolicy.FLAG_USER_AGENT_MEANINGFUL or TileSourcePolicy.FLAG_USER_AGENT_NORMALIZED ) ) { override fun getTileURLString(pMapTileIndex: Long): String { return baseUrl + (MapTileIndex.getZoom(pMapTileIndex) .toString() + "/" + MapTileIndex.getY(pMapTileIndex) + "/" + MapTileIndex.getX(pMapTileIndex) + mImageFilenameEnding) } }</ID>
|
||||
<ID>UnusedPrivateProperty:CustomTileSource.kt$CustomTileSource.Companion$private val USGS_SHADED_RELIEF = object : OnlineTileSourceBase( "USGS Shaded Relief Only", 0, 18, 256, "", arrayOf( "https://basemap.nationalmap.gov/arcgis/rest/services/USGSShadedReliefOnly/MapServer/tile/" ), "USGS", TileSourcePolicy( 2, TileSourcePolicy.FLAG_NO_PREVENTIVE or TileSourcePolicy.FLAG_USER_AGENT_MEANINGFUL or TileSourcePolicy.FLAG_USER_AGENT_NORMALIZED ) ) { override fun getTileURLString(pMapTileIndex: Long): String { return baseUrl + (MapTileIndex.getZoom(pMapTileIndex) .toString() + "/" + MapTileIndex.getY(pMapTileIndex) + "/" + MapTileIndex.getX(pMapTileIndex) + mImageFilenameEnding) } }</ID>
|
||||
<ID>UnusedPrivateProperty:MeshService.kt$MeshService$val filename = firmwareUpdateFilename ?: throw Exception("No update filename")</ID>
|
||||
<ID>UnusedPrivateProperty:MeshService.kt$MeshService$val isBluetoothInterface = a != null && a.startsWith("x")</ID>
|
||||
<ID>UtilityClassWithPublicConstructor:CustomTileSource.kt$CustomTileSource</ID>
|
||||
<ID>UtilityClassWithPublicConstructor:NetworkRepositoryModule.kt$NetworkRepositoryModule</ID>
|
||||
<ID>VariableNaming:NOAAWmsTileSource.kt$NOAAWmsTileSource$// Size of square world map in meters, using WebMerc projection. private val MAP_SIZE = 20037508.34789244 * 2</ID>
|
||||
|
@ -651,8 +750,6 @@
|
|||
<ID>VariableNaming:SafeBluetooth.kt$SafeBluetooth$private val STATUS_NOSTART = 4405</ID>
|
||||
<ID>VariableNaming:SafeBluetooth.kt$SafeBluetooth$private val STATUS_SIMFAILURE = 4406</ID>
|
||||
<ID>VariableNaming:SafeBluetooth.kt$SafeBluetooth$private val STATUS_TIMEOUT = 4404</ID>
|
||||
<ID>WildcardImport:BTScanModel.kt$import android.content.*</ID>
|
||||
<ID>WildcardImport:BTScanModel.kt$import com.geeksville.mesh.android.*</ID>
|
||||
<ID>WildcardImport:BluetoothInterface.kt$import com.geeksville.mesh.service.*</ID>
|
||||
<ID>WildcardImport:DeviceVersionTest.kt$import org.junit.Assert.*</ID>
|
||||
<ID>WildcardImport:ExampleUnitTest.kt$import org.junit.Assert.*</ID>
|
||||
|
@ -662,8 +759,6 @@
|
|||
<ID>WildcardImport:MainActivity.kt$import com.geeksville.mesh.ui.*</ID>
|
||||
<ID>WildcardImport:MeshService.kt$import com.geeksville.mesh.*</ID>
|
||||
<ID>WildcardImport:MeshService.kt$import com.geeksville.mesh.util.*</ID>
|
||||
<ID>WildcardImport:MessagesFragment.kt$import android.view.*</ID>
|
||||
<ID>WildcardImport:MessagesFragment.kt$import android.widget.*</ID>
|
||||
<ID>WildcardImport:MockInterface.kt$import com.geeksville.mesh.*</ID>
|
||||
<ID>WildcardImport:PreferenceFooter.kt$import androidx.compose.foundation.layout.*</ID>
|
||||
<ID>WildcardImport:PreferenceFooter.kt$import androidx.compose.material.*</ID>
|
||||
|
|
|
@ -304,6 +304,137 @@ exceptions:
|
|||
- 'RuntimeException'
|
||||
- 'Throwable'
|
||||
|
||||
formatting:
|
||||
active: true
|
||||
android: false
|
||||
autoCorrect: true
|
||||
AnnotationOnSeparateLine:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
AnnotationSpacing:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
ArgumentListWrapping:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
ChainWrapping:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
CommentSpacing:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
EnumEntryNameCase:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
Filename:
|
||||
active: false
|
||||
FinalNewline:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
insertFinalNewLine: true
|
||||
ImportOrdering:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
layout: 'idea'
|
||||
Indentation:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
indentSize: 4
|
||||
MaximumLineLength:
|
||||
active: false # Use default detekt rule
|
||||
maxLineLength: 120
|
||||
ModifierOrdering:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
MultiLineIfElse:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoBlankLineBeforeRbrace:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoConsecutiveBlankLines:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoEmptyClassBody:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoEmptyFirstLineInMethodBlock:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
NoLineBreakAfterElse:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoLineBreakBeforeAssignment:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoMultipleSpaces:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoSemicolons:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoTrailingSpaces:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoUnitReturn:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoUnusedImports:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoWildcardImports:
|
||||
active: true
|
||||
PackageName:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
ParameterListWrapping:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundColon:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundComma:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundCurly:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundDot:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundDoubleColon:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
SpacingAroundKeyword:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundOperators:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundParens:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundRangeOperator:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingBetweenDeclarationsWithAnnotations:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
SpacingBetweenDeclarationsWithComments:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
StringTemplate:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
TrailingCommaOnCallSite:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
useTrailingCommaOnCallSite: true
|
||||
TrailingCommaOnDeclarationSite:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
useTrailingCommaOnDeclarationSite: true
|
||||
|
||||
naming:
|
||||
active: true
|
||||
BooleanPropertyNaming:
|
||||
|
|
Ładowanie…
Reference in New Issue