chore: add detekt formatting rule set

https://detekt.dev/docs/next/rules/formatting/
pull/1313/head
andrekir 2024-10-13 23:02:05 -03:00 zatwierdzone przez Andre K
rodzic 056d4a5829
commit fe56d257f5
58 zmienionych plików z 725 dodań i 432 usunięć

Wyświetl plik

@ -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)
}
}
}
}

Wyświetl plik

@ -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")

Wyświetl plik

@ -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)
}

Wyświetl plik

@ -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()
}
}
}
}

Wyświetl plik

@ -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")
}
}
}
}

Wyświetl plik

@ -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,

Wyświetl plik

@ -29,5 +29,4 @@ interface MeshLogDao {
@Query("DELETE FROM log")
fun deleteAll()
}
}

Wyświetl plik

@ -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>)

Wyświetl plik

@ -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()

Wyświetl plik

@ -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,
}
}
}

Wyświetl plik

@ -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()

Wyświetl plik

@ -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),
;
}

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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/

Wyświetl plik

@ -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)
}

Wyświetl plik

@ -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
}
}
}
}

Wyświetl plik

@ -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)
}
}
}

Wyświetl plik

@ -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
}
}

Wyświetl plik

@ -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)
}

Wyświetl plik

@ -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)
}
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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()
}
}
}
}

Wyświetl plik

@ -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
}
}
}

Wyświetl plik

@ -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)
}
}
}

Wyświetl plik

@ -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()
}
}
}

Wyświetl plik

@ -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())
}
}
}

Wyświetl plik

@ -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(

Wyświetl plik

@ -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)
}
)
}
},

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -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")
}"
)

Wyświetl plik

@ -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 {

Wyświetl plik

@ -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()
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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()

Wyświetl plik

@ -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()
}
}
}

Wyświetl plik

@ -110,7 +110,6 @@ class UsersFragment : ScreenFragment("Users"), Logging {
parentFragmentManager.navigateToMetrics(nodeNum)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,

Wyświetl plik

@ -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 {

Wyświetl plik

@ -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

Wyświetl plik

@ -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,
)
}
)

Wyświetl plik

@ -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
)
}
},
)

Wyświetl plik

@ -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})"

Wyświetl plik

@ -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)) }

Wyświetl plik

@ -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

Wyświetl plik

@ -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 }
}
})
}

Wyświetl plik

@ -187,7 +187,7 @@ fun CannedMessageConfigItemList(
},
onSaveClicked = {
focusManager.clearFocus()
onSaveClicked(messagesInput,cannedMessageInput)
onSaveClicked(messagesInput, cannedMessageInput)
}
)
}

Wyświetl plik

@ -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 }

Wyświetl plik

@ -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

Wyświetl plik

@ -153,7 +153,6 @@ fun DisplayConfigItemList(
)
}
}
}
@Preview(showBackground = true)

Wyświetl plik

@ -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)
)

Wyświetl plik

@ -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 }
}
})
}

Wyświetl plik

@ -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 {

Wyświetl plik

@ -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) }
}
})
}

Wyświetl plik

@ -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}")

Wyświetl plik

@ -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, _ ->

Wyświetl plik

@ -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 {
}
}
}
}
}

Wyświetl plik

@ -2,6 +2,68 @@
<SmellBaseline>
<ManuallySuppressedIssues></ManuallySuppressedIssues>
<CurrentIssues>
<ID>ChainWrapping:Channel.kt$Channel$&amp;&amp;</ID>
<ID>ChainWrapping:CustomTileSource.kt$CustomTileSource.Companion.&lt;no name provided&gt;$+</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.&lt;no name provided&gt;$//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) -&gt; 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) -&gt; 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$&lt;no name provided&gt;${ }</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) -&gt; Unit, )</ID>
@ -55,27 +153,17 @@
<ID>LongMethod:CannedMessageConfigItemList.kt$@Composable fun CannedMessageConfigItemList( messages: String, cannedMessageConfig: CannedMessageConfig, enabled: Boolean, onSaveClicked: (messages: String, config: CannedMessageConfig) -&gt; Unit, )</ID>
<ID>LongMethod:ChannelFragment.kt$@Composable fun ChannelScreen( viewModel: UIViewModel = viewModel(), showSnackbar: (String) -&gt; Unit = {}, )</ID>
<ID>LongMethod:ChannelSettingsItemList.kt$@Composable fun ChannelSettingsItemList( settingsList: List&lt;ChannelSettings&gt;, modemPresetName: String = "Default", maxChannels: Int = 8, enabled: Boolean, onNegativeClicked: () -&gt; Unit = { }, onPositiveClicked: (List&lt;ChannelSettings&gt;) -&gt; 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) -&gt; Unit, )</ID>
<ID>LongMethod:DeviceConfigItemList.kt$@Composable fun DeviceConfigItemList( deviceConfig: DeviceConfig, enabled: Boolean, onSaveClicked: (DeviceConfig) -&gt; 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) -&gt; Unit, )</ID>
<ID>LongMethod:EditChannelDialog.kt$@Composable fun EditChannelDialog( channelSettings: ChannelProtos.ChannelSettings, onAddClick: (ChannelProtos.ChannelSettings) -&gt; Unit, onDismissRequest: () -&gt; Unit, modifier: Modifier = Modifier, modemPresetName: String = "Default", )</ID>
<ID>LongMethod:EditDeviceProfileDialog.kt$@Composable fun EditDeviceProfileDialog( title: String, deviceProfile: ClientOnlyProtos.DeviceProfile, onAddClick: (ClientOnlyProtos.DeviceProfile) -&gt; Unit, onDismissRequest: () -&gt; Unit, modifier: Modifier = Modifier, )</ID>
<ID>LongMethod:DropDownPreference.kt$@Composable fun &lt;T&gt; DropDownPreference( title: String, enabled: Boolean, items: List&lt;Pair&lt;T, String&gt;&gt;, selectedItem: T, onItemSelected: (T) -&gt; Unit, modifier: Modifier = Modifier, summary: String? = null, )</ID>
<ID>LongMethod:EditListPreference.kt$@Composable inline fun &lt;reified T&gt; EditListPreference( title: String, list: List&lt;T&gt;, maxCount: Int, enabled: Boolean, keyboardActions: KeyboardActions, crossinline onValuesChanged: (List&lt;T&gt;) -&gt; Unit, modifier: Modifier = Modifier, )</ID>
<ID>LongMethod:EditWaypointDialog.kt$@Composable internal fun EditWaypointDialog( waypoint: Waypoint, onSendClicked: (Waypoint) -&gt; Unit, onDeleteClicked: (Waypoint) -&gt; Unit, onDismissRequest: () -&gt; Unit, modifier: Modifier = Modifier, )</ID>
<ID>LongMethod:ExternalNotificationConfigItemList.kt$@Composable fun ExternalNotificationConfigItemList( ringtone: String, extNotificationConfig: ExternalNotificationConfig, enabled: Boolean, onSaveClicked: (ringtone: String, config: ExternalNotificationConfig) -&gt; Unit, )</ID>
<ID>LongMethod:LoRaConfigItemList.kt$@Composable fun LoRaConfigItemList( loraConfig: LoRaConfig, primarySettings: ChannelSettings, enabled: Boolean, onSaveClicked: (LoRaConfig) -&gt; Unit, )</ID>
<ID>LongMethod:MQTTConfigItemList.kt$@Composable fun MQTTConfigItemList( mqttConfig: MQTTConfig, enabled: Boolean, onSaveClicked: (MQTTConfig) -&gt; 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.&lt;no name provided&gt;$override fun onBindViewHolder(holder: ViewHolder, position: Int)</ID>
<ID>LongMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigItemList( networkConfig: NetworkConfig, enabled: Boolean, onSaveClicked: (NetworkConfig) -&gt; 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: () -&gt; 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) -&gt; Unit, )</ID>
<ID>LongMethod:PowerConfigItemList.kt$@Composable fun PowerConfigItemList( powerConfig: PowerConfig, enabled: Boolean, onSaveClicked: (PowerConfig) -&gt; 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) -&gt; Unit, )</ID>
@ -88,7 +176,6 @@
<ID>LongParameterList:NOAAWmsTileSource.kt$NOAAWmsTileSource$( aName: String, aBaseUrl: Array&lt;String&gt;, 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&lt;String&gt;, 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$&lt;no name provided&gt;$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 &amp; 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 &lt; 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 &lt; 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 -&gt; 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 (&lt;= 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 &amp;&amp; dist &lt; 1609 -&gt; "%.0f ft".format(dist.toDouble()*3.281)</ID>
<ID>MaxLineLength:NodeInfo.kt$NodeInfo$prefUnits == ConfigProtos.Config.DisplayConfig.DisplayUnits.IMPERIAL_VALUE &amp;&amp; dist &gt;= 1609 -&gt; "%.1f mi".format(dist / 1609.34)</ID>
<ID>MaxLineLength:NodeInfo.kt$NodeInfo$prefUnits == ConfigProtos.Config.DisplayConfig.DisplayUnits.METRIC_VALUE &amp;&amp; dist &lt; 1000 -&gt; "%.0f m".format(dist.toDouble())</ID>
<ID>MaxLineLength:NodeInfo.kt$NodeInfo$prefUnits == ConfigProtos.Config.DisplayConfig.DisplayUnits.METRIC_VALUE &amp;&amp; dist &gt;= 1000 -&gt; "%.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 -&gt; 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 -&gt; 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 &gt; 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 -&gt; "ShortTurbo" ModemPreset.SHORT_FAST -&gt; "ShortFast" ModemPreset.SHORT_SLOW -&gt; "ShortSlow" ModemPreset.MEDIUM_FAST -&gt; "MediumFast" ModemPreset.MEDIUM_SLOW -&gt; "MediumSlow" ModemPreset.LONG_FAST -&gt; "LongFast" ModemPreset.LONG_SLOW -&gt; "LongSlow" ModemPreset.LONG_MODERATE -&gt; "LongMod" ModemPreset.VERY_LONG_SLOW -&gt; "VLongSlow" else -&gt; "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 -&gt; .03125f 62 -&gt; .0625f 200 -&gt; .203125f 400 -&gt; .40625f 800 -&gt; .8125f 1600 -&gt; 1.6250f else -&gt; bandwidth / 1000f }</ID>
<ID>MultiLineIfElse:ContextServices.kt$MaterialAlertDialogBuilder(this) .setTitle(title) .setMessage(rationale) .setNeutralButton(R.string.cancel) { _, _ -&gt; } .setPositiveButton(R.string.accept) { _, _ -&gt; 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 -&gt; valueState = it onValueChanged(double) }</ID>
<ID>MultiLineIfElse:EditTextPreference.kt$it.toFloatOrNull()?.let { float -&gt; valueState = it onValueChanged(float) }</ID>
<ID>MultiLineIfElse:EditTextPreference.kt$it.toUIntOrNull()?.toInt()?.let { int -&gt; 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$&lt;no name provided&gt;$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 -&gt; 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.&lt;no name provided&gt;$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&lt;Nothing&gt;)</ID>
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth$work.completion.resumeWithException( BLEStatusException( status, "Bluetooth status=$status while doing ${work.tag}" ) )</ID>
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.&lt;no name provided&gt;$completeWork(status, Unit)</ID>
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.&lt;no name provided&gt;$completeWork(status, characteristic)</ID>
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.&lt;no name provided&gt;$dropAndReconnect()</ID>
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.&lt;no name provided&gt;$errormsg("Ignoring bogus onMtuChanged")</ID>
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.&lt;no name provided&gt;$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.&lt;no name provided&gt;$lostConnection("lost connection")</ID>
<ID>MultiLineIfElse:SafeBluetooth.kt$SafeBluetooth.&lt;no name provided&gt;$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 -&gt; ChannelProtos.Channel.Role.PRIMARY in 1..new.lastIndex -&gt; ChannelProtos.Channel.Role.SECONDARY else -&gt; ChannelProtos.Channel.Role.DISABLED } index = i settings = new.getOrNull(i) ?: channelSettings { } })</ID>
<ID>NestedBlockDepth:LanguageUtils.kt$LanguageUtils$fun getLanguageTags(context: Context): Map&lt;String, String&gt;</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&lt;Float&gt;)</ID>
<ID>ParameterListWrapping:AppPrefs.kt$StringPref$(thisRef: AppPrefs, prop: KProperty&lt;String&gt;)</ID>
<ID>ParameterListWrapping:SafeBluetooth.kt$SafeBluetooth$( c: BluetoothGattCharacteristic, cont: Continuation&lt;BluetoothGattCharacteristic&gt;, timeout: Long = 0 )</ID>
<ID>ParameterListWrapping:SafeBluetooth.kt$SafeBluetooth$( c: BluetoothGattCharacteristic, cont: Continuation&lt;Unit&gt;, timeout: Long = 0 )</ID>
<ID>ParameterListWrapping:SafeBluetooth.kt$SafeBluetooth$( c: BluetoothGattCharacteristic, v: ByteArray, cont: Continuation&lt;BluetoothGattCharacteristic&gt;, timeout: Long = 0 )</ID>
<ID>ParameterListWrapping:SafeBluetooth.kt$SafeBluetooth$( c: BluetoothGattDescriptor, cont: Continuation&lt;BluetoothGattDescriptor&gt;, 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.&lt;no name provided&gt;$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$&lt;no name provided&gt; : 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 &amp;&amp; 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>

Wyświetl plik

@ -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: