2020-02-17 13:34:52 -08:00
|
|
|
package com.geeksville.mesh.model
|
|
|
|
|
|
2020-02-18 10:40:02 -08:00
|
|
|
import android.content.Context
|
2020-03-02 08:41:16 -08:00
|
|
|
import android.content.SharedPreferences
|
2020-03-02 07:46:03 -08:00
|
|
|
import android.graphics.Bitmap
|
2020-02-18 12:22:45 -08:00
|
|
|
import android.os.RemoteException
|
2020-02-17 13:34:52 -08:00
|
|
|
import android.util.Base64
|
|
|
|
|
import androidx.compose.mutableStateOf
|
2020-02-18 10:40:02 -08:00
|
|
|
import androidx.core.content.edit
|
2020-02-29 13:21:05 -08:00
|
|
|
import com.geeksville.android.Logging
|
2020-02-17 15:39:49 -08:00
|
|
|
import com.geeksville.mesh.IMeshService
|
2020-02-17 13:34:52 -08:00
|
|
|
import com.geeksville.mesh.MeshProtos
|
2020-03-15 16:30:12 -07:00
|
|
|
import com.geeksville.mesh.MeshProtos.ChannelSettings.ModemConfig
|
2020-02-18 10:40:02 -08:00
|
|
|
import com.geeksville.mesh.ui.getInitials
|
2020-03-02 07:46:03 -08:00
|
|
|
import com.google.zxing.BarcodeFormat
|
|
|
|
|
import com.google.zxing.MultiFormatWriter
|
|
|
|
|
import com.journeyapps.barcodescanner.BarcodeEncoder
|
2020-02-17 13:34:52 -08:00
|
|
|
|
2020-03-15 16:30:12 -07:00
|
|
|
data class Channel(
|
|
|
|
|
val name: String,
|
|
|
|
|
val num: Int,
|
|
|
|
|
val modemConfig: ModemConfig = ModemConfig.Bw125Cr45Sf128
|
|
|
|
|
) {
|
|
|
|
|
companion object {
|
|
|
|
|
// Placeholder when emulating
|
|
|
|
|
val emulated = Channel("Default", 7)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constructor(c: MeshProtos.ChannelSettings) : this(c.name, c.channelNum, c.modemConfig) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* a nice readable description of modem configs
|
|
|
|
|
*/
|
|
|
|
|
fun ModemConfig.toHumanString(): String = when (this) {
|
|
|
|
|
ModemConfig.Bw125Cr45Sf128 -> "Medium range (but fast)"
|
|
|
|
|
ModemConfig.Bw500Cr45Sf128 -> "Short range (but fast)"
|
|
|
|
|
ModemConfig.Bw31_25Cr48Sf512 -> "Long range (but slower)"
|
|
|
|
|
ModemConfig.Bw125Cr48Sf4096 -> "Very long range (but slow)"
|
|
|
|
|
else -> this.toString()
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-17 13:34:52 -08:00
|
|
|
/// FIXME - figure out how to merge this staate with the AppStatus Model
|
2020-03-02 07:46:03 -08:00
|
|
|
object UIState : Logging {
|
2020-02-17 13:34:52 -08:00
|
|
|
|
|
|
|
|
/// Kinda ugly - created in the activity but used from Compose - figure out if there is a cleaner way GIXME
|
|
|
|
|
// lateinit var googleSignInClient: GoogleSignInClient
|
|
|
|
|
|
2020-02-17 15:39:49 -08:00
|
|
|
var meshService: IMeshService? = null
|
2020-02-17 13:34:52 -08:00
|
|
|
|
|
|
|
|
/// Are we connected to our radio device
|
|
|
|
|
val isConnected = mutableStateOf(false)
|
|
|
|
|
|
|
|
|
|
/// various radio settings (including the channel)
|
2020-03-02 08:41:16 -08:00
|
|
|
private val radioConfig = mutableStateOf<MeshProtos.RadioConfig?>(null)
|
2020-02-17 13:34:52 -08:00
|
|
|
|
|
|
|
|
/// our name in hte radio
|
|
|
|
|
/// Note, we generate owner initials automatically for now
|
2020-02-18 12:22:45 -08:00
|
|
|
/// our activity will read this from prefs or set it to the empty string
|
|
|
|
|
var ownerName: String = "MrInIDE Ownername"
|
2020-02-17 13:34:52 -08:00
|
|
|
|
2020-03-15 16:30:12 -07:00
|
|
|
fun getChannel() = radioConfig.value?.channelSettings?.let { Channel(it) }
|
|
|
|
|
|
2020-02-17 13:34:52 -08:00
|
|
|
/// Return an URL that represents the current channel values
|
2020-03-02 08:41:16 -08:00
|
|
|
fun getChannelUrl(context: Context): String {
|
|
|
|
|
// If we have a valid radio config use it, othterwise use whatever we have saved in the prefs
|
|
|
|
|
val radio = radioConfig.value
|
|
|
|
|
if (radio != null) {
|
|
|
|
|
val settings = radio.channelSettings
|
|
|
|
|
val channelBytes = settings.toByteArray()
|
2020-02-17 13:34:52 -08:00
|
|
|
val enc = Base64.encodeToString(channelBytes, Base64.URL_SAFE + Base64.NO_WRAP)
|
|
|
|
|
|
|
|
|
|
return "https://www.meshtastic.org/c/$enc"
|
2020-03-02 08:41:16 -08:00
|
|
|
} else {
|
|
|
|
|
return getPreferences(context).getString(
|
|
|
|
|
"owner",
|
|
|
|
|
"https://www.meshtastic.org/c/unset"
|
|
|
|
|
)!!
|
2020-02-17 13:34:52 -08:00
|
|
|
}
|
2020-03-02 08:41:16 -08:00
|
|
|
}
|
|
|
|
|
|
2020-03-15 16:30:12 -07:00
|
|
|
fun getChannelQR(context: Context): Bitmap {
|
2020-03-02 08:41:16 -08:00
|
|
|
val multiFormatWriter = MultiFormatWriter()
|
|
|
|
|
|
|
|
|
|
val bitMatrix =
|
|
|
|
|
multiFormatWriter.encode(getChannelUrl(context), BarcodeFormat.QR_CODE, 192, 192);
|
|
|
|
|
val barcodeEncoder = BarcodeEncoder()
|
|
|
|
|
return barcodeEncoder.createBitmap(bitMatrix)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun getPreferences(context: Context): SharedPreferences =
|
|
|
|
|
context.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE)
|
2020-02-18 10:40:02 -08:00
|
|
|
|
2020-03-02 08:41:16 -08:00
|
|
|
/// Set the radio config (also updates our saved copy in preferences)
|
|
|
|
|
fun setRadioConfig(context: Context, c: MeshProtos.RadioConfig) {
|
|
|
|
|
radioConfig.value = c
|
2020-03-02 07:46:03 -08:00
|
|
|
|
2020-03-02 08:41:16 -08:00
|
|
|
getPreferences(context).edit(commit = true) {
|
|
|
|
|
this.putString("channel-url", getChannelUrl(context))
|
2020-03-02 07:46:03 -08:00
|
|
|
}
|
2020-03-02 08:41:16 -08:00
|
|
|
}
|
2020-03-02 07:46:03 -08:00
|
|
|
|
2020-02-18 10:40:02 -08:00
|
|
|
// clean up all this nasty owner state management FIXME
|
|
|
|
|
fun setOwner(context: Context, s: String? = null) {
|
2020-02-18 12:22:45 -08:00
|
|
|
|
2020-02-18 10:40:02 -08:00
|
|
|
if (s != null) {
|
|
|
|
|
ownerName = s
|
2020-02-18 12:22:45 -08:00
|
|
|
|
|
|
|
|
// note: we allow an empty userstring to be written to prefs
|
2020-03-02 08:41:16 -08:00
|
|
|
getPreferences(context).edit(commit = true) {
|
2020-02-18 10:40:02 -08:00
|
|
|
putString("owner", s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Note: we are careful to not set a new unique ID
|
2020-02-18 12:22:45 -08:00
|
|
|
if (ownerName.isNotEmpty())
|
|
|
|
|
try {
|
|
|
|
|
meshService?.setOwner(
|
|
|
|
|
null,
|
|
|
|
|
ownerName,
|
|
|
|
|
getInitials(ownerName)
|
|
|
|
|
) // Note: we use ?. here because we might be running in the emulator
|
|
|
|
|
} catch (ex: RemoteException) {
|
2020-02-29 13:21:05 -08:00
|
|
|
errormsg("Can't set username on device, is device offline? ${ex.message}")
|
2020-02-18 12:22:45 -08:00
|
|
|
}
|
2020-02-18 10:40:02 -08:00
|
|
|
}
|
2020-02-17 13:34:52 -08:00
|
|
|
}
|