From aa79ee4335aa65d619ff3838b0fec9f257ce17d8 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Wed, 3 Mar 2021 14:43:29 +0800 Subject: [PATCH] make our simulator work like 1.2 --- .../geeksville/mesh/service/MockInterface.kt | 61 ++++++++++++++++--- .../com/geeksville/mesh/service/SimRadio.kt | 51 ---------------- .../geeksville/mesh/ui/SettingsFragment.kt | 2 +- app/src/main/res/layout/settings_fragment.xml | 2 + app/src/main/res/values/protobufs.xml | 15 +++++ app/src/main/res/values/styles.xml | 14 +++++ 6 files changed, 85 insertions(+), 60 deletions(-) delete mode 100644 app/src/main/java/com/geeksville/mesh/service/SimRadio.kt create mode 100644 app/src/main/res/values/protobufs.xml diff --git a/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt b/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt index 84d3aab53..c83b0b00d 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt @@ -26,13 +26,40 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi override fun handleSendToRadio(p: ByteArray) { val pr = MeshProtos.ToRadio.parseFrom(p) + val data = if (pr.hasPacket()) pr.packet.decoded else null + when { pr.wantConfigId != 0 -> sendConfigResponse(pr.wantConfigId) + data != null && data.portnum == Portnums.PortNum.ADMIN_APP -> handleAdminPacket( + pr, + AdminProtos.AdminMessage.parseFrom(data.payload) + ) pr.hasPacket() && pr.packet.wantAck -> sendFakeAck(pr) else -> info("Ignoring data sent to mock interface $pr") } } + private fun handleAdminPacket(pr: MeshProtos.ToRadio, d: AdminProtos.AdminMessage) { + if (d.getRadioRequest) + sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) { + getRadioResponse = RadioConfigProtos.RadioConfig.newBuilder().apply { + + preferences = RadioConfigProtos.RadioConfig.UserPreferences.newBuilder().apply { + region = RadioConfigProtos.RegionCode.TW + // FIXME set critical times? + }.build() + }.build() + } + + if (d.getChannelRequest != 0) + sendAdmin(pr.packet.to, pr.packet.from, pr.packet.id) { + getChannelResponse = ChannelProtos.Channel.newBuilder().apply { + index = d.getChannelRequest - 1 // 0 based on the response + role = if(d.getChannelRequest == 1) ChannelProtos.Channel.Role.PRIMARY else ChannelProtos.Channel.Role.DISABLED + }.build() + } + } + override fun close() { info("Closing the mock interface") } @@ -53,8 +80,7 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi }.build() } - - private fun makeAck(fromIn: Int, toIn: Int, msgId: Int) = + private fun makeDataPacket(fromIn: Int, toIn: Int, data: MeshProtos.Data.Builder) = MeshProtos.FromRadio.newBuilder().apply { packet = MeshProtos.MeshPacket.newBuilder().apply { id = messageNumSequence.next() @@ -62,15 +88,34 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi to = toIn rxTime = (System.currentTimeMillis() / 1000).toInt() rxSnr = 1.5f - decoded = MeshProtos.Data.newBuilder().apply { - portnum = Portnums.PortNum.ROUTING_APP - payload = MeshProtos.Routing.newBuilder().apply { - }.build().toByteString() - requestId = msgId - }.build() + decoded = data.build() }.build() } + private fun makeAck(fromIn: Int, toIn: Int, msgId: Int) = + makeDataPacket(fromIn, toIn, MeshProtos.Data.newBuilder().apply { + portnum = Portnums.PortNum.ROUTING_APP + payload = MeshProtos.Routing.newBuilder().apply { + }.build().toByteString() + requestId = msgId + }) + + private fun sendAdmin( + fromIn: Int, + toIn: Int, + reqId: Int, + initFn: AdminProtos.AdminMessage.Builder.() -> Unit + ) { + val p = makeDataPacket(fromIn, toIn, MeshProtos.Data.newBuilder().apply { + portnum = Portnums.PortNum.ADMIN_APP + payload = AdminProtos.AdminMessage.newBuilder().also { + initFn(it) + }.build().toByteString() + requestId = reqId + }) + service.handleFromRadio(p.build().toByteArray()) + } + /// Send a fake ack packet back if the sender asked for want_ack private fun sendFakeAck(pr: MeshProtos.ToRadio) { service.handleFromRadio( diff --git a/app/src/main/java/com/geeksville/mesh/service/SimRadio.kt b/app/src/main/java/com/geeksville/mesh/service/SimRadio.kt deleted file mode 100644 index 36b87b40d..000000000 --- a/app/src/main/java/com/geeksville/mesh/service/SimRadio.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.geeksville.mesh - -import android.content.Context -import com.geeksville.mesh.service.RadioInterfaceService - -class SimRadio(private val context: Context) { - - /** - * When simulating we parse these MeshPackets as if they arrived at startup - * Send broadcast them after we receive a ToRadio.WantNodes message. - * - * Our fake net has three nodes - * - * +16508675309, nodenum 9 - our node - * +16508675310, nodenum 10 - some other node, name Bob One/BO - * (eventually) +16508675311, nodenum 11 - some other node - */ - private val simInitPackets = - arrayOf( - """ { "from": 10, "to": 9, "payload": { "user": { "id": "+16508675310", "longName": "Bob One", "shortName": "BO" }}} """, - """ { "from": 10, "to": 9, "payload": { "data": { "payload": "aGVsbG8gd29ybGQ=", "typ": 0 }}} """, // SIGNAL_OPAQUE - """ { "from": 10, "to": 9, "payload": { "data": { "payload": "aGVsbG8gd29ybGQ=", "typ": 1 }}} """, // CLEAR_TEXT - """ { "from": 10, "to": 9, "payload": { "data": { "payload": "", "typ": 2 }}} """ // CLEAR_READACK - ) - - fun start() { - // FIXME, do this sim startup elsewhere, because waiting for a packet from MeshService - // isn't right, because that service can't successfully send radio packets until it knows - // our node num - // Instead a separate sim radio thing can come in at startup and force these broadcasts to happen - // at the right time - // Send a fake my_node_num response - /* FIXME - change to use new radio info message - RadioInterfaceService.broadcastReceivedFromRadio( - context, - MeshProtos.FromRadio.newBuilder().apply { - myNodeNum = 9 - }.build().toByteArray() - ) */ - - simInitPackets.forEach { _ -> - val fromRadio = MeshProtos.FromRadio.newBuilder().apply { - packet = MeshProtos.MeshPacket.newBuilder().apply { - // jsonParser.merge(json, this) - }.build() - }.build() - - RadioInterfaceService.broadcastReceivedFromRadio(context, fromRadio.toByteArray()) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt index ae77be60c..86c20fc2c 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -590,7 +590,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { val spinner = binding.regionSpinner val regionAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, regions) regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - spinner.adapter = regionAdapter + // spinner.adapter = regionAdapter model.ownerName.observe(viewLifecycleOwner, { name -> binding.usernameEditText.setText(name) diff --git a/app/src/main/res/layout/settings_fragment.xml b/app/src/main/res/layout/settings_fragment.xml index 80c7a6714..e34fb6518 100644 --- a/app/src/main/res/layout/settings_fragment.xml +++ b/app/src/main/res/layout/settings_fragment.xml @@ -62,8 +62,10 @@ android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="16dp" + android:theme="@style/AppTheme.Spinner" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/usernameView" + android:entries="@array/regions" app:layout_constraintTop_toTopOf="parent" /> diff --git a/app/src/main/res/values/protobufs.xml b/app/src/main/res/values/protobufs.xml new file mode 100644 index 000000000..190471fc4 --- /dev/null +++ b/app/src/main/res/values/protobufs.xml @@ -0,0 +1,15 @@ + + + + + Unset + US + EU433 + EU865 + CN + JP + ANZ + KR + TW + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 691680617..e36ac68c6 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -13,6 +13,20 @@ @style/menu_item_color + + + + +