refactor(ble): Centralize BLE logic into a core module (#4550)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-02-20 06:41:52 -06:00 committed by GitHub
parent 7a68802bc2
commit 6bfa5b5f70
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
214 changed files with 3471 additions and 2405 deletions

View file

@ -25,9 +25,9 @@ import kotlinx.parcelize.TypeParceler
import kotlinx.serialization.Serializable
import okio.ByteString
import okio.ByteString.Companion.toByteString
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.model.util.ByteStringParceler
import org.meshtastic.core.model.util.ByteStringSerializer
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.MeshPacket
import org.meshtastic.proto.PortNum
import org.meshtastic.proto.Waypoint

View file

@ -19,10 +19,10 @@ package org.meshtastic.core.model
import android.graphics.Color
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import org.meshtastic.core.common.util.nowSeconds
import org.meshtastic.core.model.util.anonymize
import org.meshtastic.core.model.util.bearing
import org.meshtastic.core.model.util.latLongToMeter
import org.meshtastic.core.model.util.nowSeconds
import org.meshtastic.core.model.util.onlineTimeThreshold
import org.meshtastic.proto.Config
import org.meshtastic.proto.HardwareModel

View file

@ -16,6 +16,9 @@
*/
package org.meshtastic.core.model.util
import org.meshtastic.core.common.util.nowInstant
import org.meshtastic.core.common.util.toDate
import org.meshtastic.core.common.util.toInstant
import org.meshtastic.core.model.util.TimeConstants.HOURS_PER_DAY
import java.text.DateFormat
import kotlin.time.Duration

View file

@ -86,3 +86,35 @@ fun Telemetry.hasValidEnvironmentMetrics(): Boolean {
val metrics = this.environment_metrics ?: return false
return metrics.relative_humidity != null && metrics.temperature != null && !metrics.temperature!!.isNaN()
}
/**
* Given a human name, strip out the first letter of the first three words and return that as the initials for that
* user, ignoring emojis. 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.
*/
@Suppress("MagicNumber")
fun getInitials(fullName: String): String {
val maxInitialLength = 4
val minWordCountForInitials = 2
val name = fullName.trim().withoutEmojis()
val words = name.split(Regex("\\s+")).filter { it.isNotEmpty() }
val initials =
when (words.size) {
in 0 until minWordCountForInitials -> {
val nameWithoutVowels =
if (name.isNotEmpty()) {
name.first() + name.drop(1).filterNot { c -> c.lowercase() in "aeiou" }
} else {
""
}
if (nameWithoutVowels.length >= maxInitialLength) nameWithoutVowels else name
}
else -> words.map { it.first() }.joinToString("")
}
return initials.take(maxInitialLength)
}
fun String.withoutEmojis(): String = filterNot { char -> char.isSurrogate() }

View file

@ -21,6 +21,9 @@ import androidx.annotation.RequiresApi
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toJavaZoneId
import kotlinx.datetime.toLocalDateTime
import org.meshtastic.core.common.util.nowInstant
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.common.util.systemTimeZone
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.ZonedDateTime

View file

@ -1,58 +0,0 @@
/*
* Copyright (c) 2025-2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.meshtastic.core.model.util
import kotlinx.datetime.TimeZone
import java.util.Date
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import kotlin.time.Clock
import kotlin.time.Duration
import kotlin.time.Instant
/**
* Awaits the latch for the given [Duration].
*
* @param timeout The maximum time to wait.
* @return `true` if the count reached zero and `false` if the waiting time elapsed before the count reached zero.
*/
fun CountDownLatch.await(timeout: Duration): Boolean = this.await(timeout.inWholeMilliseconds, TimeUnit.MILLISECONDS)
/** Accessor for the current time in milliseconds. */
val nowMillis: Long
get() = nowInstant.toEpochMilliseconds()
/** Accessor for the current time as a stable [Instant]. */
val nowInstant: Instant
get() = Clock.System.now()
/** Accessor for the current time in seconds. */
val nowSeconds: Long
get() = nowInstant.epochSeconds
/** Accessor for the system default time zone. */
val systemTimeZone: TimeZone
get() = TimeZone.currentSystemDefault()
/** Converts this [Instant] to a legacy [Date]. */
fun Instant.toDate(): Date = Date(this.toEpochMilliseconds())
/** Converts these milliseconds to an [Instant]. */
fun Long.toInstant(): Instant = Instant.fromEpochMilliseconds(this)
/** Converts these seconds to an [Instant]. */
fun Int.secondsToInstant(): Instant = Instant.fromEpochSeconds(this.toLong())

View file

@ -20,6 +20,12 @@ import kotlinx.datetime.TimeZone
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.meshtastic.core.common.util.await
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.core.common.util.nowSeconds
import org.meshtastic.core.common.util.secondsToInstant
import org.meshtastic.core.common.util.toDate
import org.meshtastic.core.common.util.toInstant
import java.util.concurrent.CountDownLatch
import kotlin.time.Clock
import kotlin.time.Duration.Companion.milliseconds