Merge pull request #44 from geeksville/dev

Misc bug fixes
pull/46/head
Kevin Hester 2020-06-12 20:27:35 -07:00 zatwierdzone przez GitHub
commit 60b2fe6768
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
7 zmienionych plików z 54 dodań i 33 usunięć

Wyświetl plik

@ -1,7 +1,6 @@
# Remaining tasks before declaring 1.0 # Remaining tasks before declaring 1.0
* add a low level settings screen (let user change any of the RadioConfig parameters) * add a low level settings screen (let user change any of the RadioConfig parameters)
* if user edits the channel, generate a new AES256 key
* add play store link with https://developers.google.com/analytics/devguides/collection/android/v4/campaigns#google-play-url-builder and the play icon * add play store link with https://developers.google.com/analytics/devguides/collection/android/v4/campaigns#google-play-url-builder and the play icon
Things for the betaish period. Things for the betaish period.

Wyświetl plik

@ -17,8 +17,8 @@ android {
applicationId "com.geeksville.mesh" applicationId "com.geeksville.mesh"
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works) minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
targetSdkVersion 29 targetSdkVersion 29
versionCode 176 versionCode 10771 // format is Mmmss (where M is 1+the numeric major number
versionName "0.7.6" versionName "0.7.71"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {

Wyświetl plik

@ -14,10 +14,12 @@ data class Channel(
val settings: MeshProtos.ChannelSettings = MeshProtos.ChannelSettings.getDefaultInstance() val settings: MeshProtos.ChannelSettings = MeshProtos.ChannelSettings.getDefaultInstance()
) { ) {
companion object { companion object {
// Note: this string _SHOULD NOT BE LOCALIZED_ because it directly hashes to values used on the device for the default channel name.
val defaultChannelName = "Default"
// Placeholder when emulating // Placeholder when emulating
val emulated = Channel( val emulated = Channel(
// Note: this string _SHOULD NOT BE LOCALIZED_ because it directly hashes to values used on the device for the default channel name. MeshProtos.ChannelSettings.newBuilder().setName(defaultChannelName)
MeshProtos.ChannelSettings.newBuilder().setName("Default")
.setModemConfig(MeshProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128).build() .setModemConfig(MeshProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128).build()
) )

Wyświetl plik

@ -620,6 +620,7 @@ class MeshService : Service(), Logging {
private var radioConfig: MeshProtos.RadioConfig? = null private var radioConfig: MeshProtos.RadioConfig? = null
/// 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 private var haveNodeDB = false
// The database of active nodes, index is the node number // The database of active nodes, index is the node number
@ -933,6 +934,7 @@ class MeshService : Service(), Logging {
// decided to pass through to us (except for broadcast packets) // decided to pass through to us (except for broadcast packets)
//val toNum = packet.to //val toNum = packet.to
debug("Recieved: $packet")
val p = packet.decoded val p = packet.decoded
// If the rxTime was not set by the device (because device software was old), guess at a time // If the rxTime was not set by the device (because device software was old), guess at a time
@ -1154,29 +1156,30 @@ class MeshService : Service(), Logging {
} }
RadioInterfaceService.RECEIVE_FROMRADIO_ACTION -> { RadioInterfaceService.RECEIVE_FROMRADIO_ACTION -> {
val proto = val bytes = intent.getByteArrayExtra(EXTRA_PAYLOAD)!!
MeshProtos.FromRadio.parseFrom( try {
intent.getByteArrayExtra( val proto =
EXTRA_PAYLOAD MeshProtos.FromRadio.parseFrom(bytes)
)!! info("Received from radio service: ${proto.toOneLineString()}")
) when (proto.variantCase.number) {
info("Received from radio service: ${proto.toOneLineString()}") MeshProtos.FromRadio.PACKET_FIELD_NUMBER -> handleReceivedMeshPacket(
when (proto.variantCase.number) { proto.packet
MeshProtos.FromRadio.PACKET_FIELD_NUMBER -> handleReceivedMeshPacket( )
proto.packet
)
MeshProtos.FromRadio.CONFIG_COMPLETE_ID_FIELD_NUMBER -> handleConfigComplete( MeshProtos.FromRadio.CONFIG_COMPLETE_ID_FIELD_NUMBER -> handleConfigComplete(
proto.configCompleteId proto.configCompleteId
) )
MeshProtos.FromRadio.MY_INFO_FIELD_NUMBER -> handleMyInfo(proto.myInfo) MeshProtos.FromRadio.MY_INFO_FIELD_NUMBER -> handleMyInfo(proto.myInfo)
MeshProtos.FromRadio.NODE_INFO_FIELD_NUMBER -> handleNodeInfo(proto.nodeInfo) MeshProtos.FromRadio.NODE_INFO_FIELD_NUMBER -> handleNodeInfo(proto.nodeInfo)
MeshProtos.FromRadio.RADIO_FIELD_NUMBER -> handleRadioConfig(proto.radio) MeshProtos.FromRadio.RADIO_FIELD_NUMBER -> handleRadioConfig(proto.radio)
else -> errormsg("Unexpected FromRadio variant") else -> errormsg("Unexpected FromRadio variant")
}
} catch (ex: InvalidProtocolBufferException) {
Exceptions.report(ex, "Invalid Protobuf from radio, len=${bytes.size}")
} }
} }

Wyświetl plik

@ -18,12 +18,15 @@ import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging import com.geeksville.android.Logging
import com.geeksville.android.hideKeyboard import com.geeksville.android.hideKeyboard
import com.geeksville.mesh.R import com.geeksville.mesh.R
import com.geeksville.mesh.model.Channel
import com.geeksville.mesh.model.UIViewModel import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.service.MeshService import com.geeksville.mesh.service.MeshService
import com.geeksville.util.Exceptions import com.geeksville.util.Exceptions
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.protobuf.ByteString
import kotlinx.android.synthetic.main.channel_fragment.* import kotlinx.android.synthetic.main.channel_fragment.*
import java.security.SecureRandom
// Make an image view dim // Make an image view dim
@ -142,7 +145,15 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
UIViewModel.getChannel(model.radioConfig.value)?.let { old -> UIViewModel.getChannel(model.radioConfig.value)?.let { old ->
val newSettings = old.settings.toBuilder() val newSettings = old.settings.toBuilder()
newSettings.name = channelNameEdit.text.toString().trim() newSettings.name = channelNameEdit.text.toString().trim()
// FIXME, regenerate a new preshared key!
// Generate a new AES256 key (for any channel not named Default)
if (newSettings.name != Channel.defaultChannelName) {
debug("ASSIGNING NEW AES256 KEY")
val random = SecureRandom()
val bytes = ByteArray(32)
random.nextBytes(bytes)
newSettings.psk = ByteString.copyFrom(bytes)
}
// Try to change the radio, if it fails, tell the user why and throw away their redits // Try to change the radio, if it fails, tell the user why and throw away their redits
try { try {
@ -150,7 +161,7 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
// Since we are writing to radioconfig, that will trigger the rest of the GUI update (QR code etc) // Since we are writing to radioconfig, that will trigger the rest of the GUI update (QR code etc)
} catch (ex: RemoteException) { } catch (ex: RemoteException) {
setGUIfromModel() // Throw away user edits setGUIfromModel() // Throw away user edits
// Tell the user to try again // Tell the user to try again
Snackbar.make( Snackbar.make(
editableCheckbox, editableCheckbox,

Wyświetl plik

@ -6,7 +6,6 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import com.geeksville.android.GeeksvilleApplication import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging import com.geeksville.android.Logging
import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.NodeInfo
@ -131,7 +130,7 @@ class MapFragment : ScreenFragment("Map"), Logging {
} }
var mapView: MapView? = null var mapView: MapView? = null
var mapboxMap: MapboxMap? = null
override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) { override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) {
super.onViewCreated(viewIn, savedInstanceState) super.onViewCreated(viewIn, savedInstanceState)
@ -146,6 +145,7 @@ class MapFragment : ScreenFragment("Map"), Logging {
// Each time the pane is shown start fetching new map info (we do this here instead of // Each time the pane is shown start fetching new map info (we do this here instead of
// onCreate because getMapAsync can die in native code if the view goes away) // onCreate because getMapAsync can die in native code if the view goes away)
v.getMapAsync { map -> v.getMapAsync { map ->
mapboxMap = map
if (view != null) { // it might have gone away by now if (view != null) { // it might have gone away by now
// val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24) // val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24)
@ -159,11 +159,6 @@ class MapFragment : ScreenFragment("Map"), Logging {
style.addLayer(labelLayer) style.addLayer(labelLayer)
} }
model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes ->
if (view != null)
onNodesChanged(map, nodes.values)
})
//map.uiSettings.isScrollGesturesEnabled = true //map.uiSettings.isScrollGesturesEnabled = true
//map.uiSettings.isZoomGesturesEnabled = true //map.uiSettings.isZoomGesturesEnabled = true
} }
@ -190,6 +185,16 @@ class MapFragment : ScreenFragment("Map"), Logging {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
mapView?.onResume() mapView?.onResume()
// FIXME: for now we just set the node positions when the user pages to the map - because
// otherwise we try to update in the background which breaks mapbox native code (when view is not shown
mapboxMap?.let { map ->
// model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes ->
model.nodeDB.nodes.value?.values?.let {
onNodesChanged(map, it)
}
//})
}
} }
override fun onDestroy() { override fun onDestroy() {

Wyświetl plik

@ -574,7 +574,8 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
b.text = device.name b.text = device.name
b.id = View.generateViewId() b.id = View.generateViewId()
b.isEnabled = enabled b.isEnabled = enabled
b.isChecked = device.address == scanModel.selectedNotNull b.isChecked =
device.address == scanModel.selectedNotNull && device.bonded // Only show checkbox if device is still paired
deviceRadioGroup.addView(b) deviceRadioGroup.addView(b)
// Once we have at least one device, don't show the "looking for" animation - it makes uers think // Once we have at least one device, don't show the "looking for" animation - it makes uers think