kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
make our simulator work like 1.2
rodzic
b53acd206b
commit
aa79ee4335
|
@ -26,13 +26,40 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi
|
||||||
override fun handleSendToRadio(p: ByteArray) {
|
override fun handleSendToRadio(p: ByteArray) {
|
||||||
val pr = MeshProtos.ToRadio.parseFrom(p)
|
val pr = MeshProtos.ToRadio.parseFrom(p)
|
||||||
|
|
||||||
|
val data = if (pr.hasPacket()) pr.packet.decoded else null
|
||||||
|
|
||||||
when {
|
when {
|
||||||
pr.wantConfigId != 0 -> sendConfigResponse(pr.wantConfigId)
|
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)
|
pr.hasPacket() && pr.packet.wantAck -> sendFakeAck(pr)
|
||||||
else -> info("Ignoring data sent to mock interface $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() {
|
override fun close() {
|
||||||
info("Closing the mock interface")
|
info("Closing the mock interface")
|
||||||
}
|
}
|
||||||
|
@ -53,8 +80,7 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun makeDataPacket(fromIn: Int, toIn: Int, data: MeshProtos.Data.Builder) =
|
||||||
private fun makeAck(fromIn: Int, toIn: Int, msgId: Int) =
|
|
||||||
MeshProtos.FromRadio.newBuilder().apply {
|
MeshProtos.FromRadio.newBuilder().apply {
|
||||||
packet = MeshProtos.MeshPacket.newBuilder().apply {
|
packet = MeshProtos.MeshPacket.newBuilder().apply {
|
||||||
id = messageNumSequence.next()
|
id = messageNumSequence.next()
|
||||||
|
@ -62,13 +88,32 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi
|
||||||
to = toIn
|
to = toIn
|
||||||
rxTime = (System.currentTimeMillis() / 1000).toInt()
|
rxTime = (System.currentTimeMillis() / 1000).toInt()
|
||||||
rxSnr = 1.5f
|
rxSnr = 1.5f
|
||||||
decoded = MeshProtos.Data.newBuilder().apply {
|
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
|
portnum = Portnums.PortNum.ROUTING_APP
|
||||||
payload = MeshProtos.Routing.newBuilder().apply {
|
payload = MeshProtos.Routing.newBuilder().apply {
|
||||||
}.build().toByteString()
|
}.build().toByteString()
|
||||||
requestId = msgId
|
requestId = msgId
|
||||||
}.build()
|
})
|
||||||
}.build()
|
|
||||||
|
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
|
/// Send a fake ack packet back if the sender asked for want_ack
|
||||||
|
|
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -590,7 +590,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
val spinner = binding.regionSpinner
|
val spinner = binding.regionSpinner
|
||||||
val regionAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, regions)
|
val regionAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, regions)
|
||||||
regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
spinner.adapter = regionAdapter
|
// spinner.adapter = regionAdapter
|
||||||
|
|
||||||
model.ownerName.observe(viewLifecycleOwner, { name ->
|
model.ownerName.observe(viewLifecycleOwner, { name ->
|
||||||
binding.usernameEditText.setText(name)
|
binding.usernameEditText.setText(name)
|
||||||
|
|
|
@ -62,8 +62,10 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
|
android:theme="@style/AppTheme.Spinner"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/usernameView"
|
app:layout_constraintStart_toEndOf="@+id/usernameView"
|
||||||
|
android:entries="@array/regions"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<array name="regions">
|
||||||
|
<!-- FIXME - better to get this through reflection -->
|
||||||
|
<item>Unset</item>
|
||||||
|
<item>US</item>
|
||||||
|
<item>EU433</item>
|
||||||
|
<item>EU865</item>
|
||||||
|
<item>CN</item>
|
||||||
|
<item>JP</item>
|
||||||
|
<item>ANZ</item>
|
||||||
|
<item>KR</item>
|
||||||
|
<item>TW</item>
|
||||||
|
</array>
|
||||||
|
</resources>
|
|
@ -13,6 +13,20 @@
|
||||||
<item name="android:itemTextAppearance">@style/menu_item_color</item>
|
<item name="android:itemTextAppearance">@style/menu_item_color</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="AppTheme.Spinner">
|
||||||
|
<item name="android:spinnerItemStyle">@style/SpinnerItem</item>
|
||||||
|
<item name="android:spinnerDropDownItemStyle">@style/SpinnerDropDownItem</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="SpinnerItem">
|
||||||
|
<item name="android:gravity">right|center_vertical</item>
|
||||||
|
<item name="android:paddingRight">16dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="SpinnerDropDownItem">
|
||||||
|
<item name="android:gravity">right|center_vertical</item>
|
||||||
|
<item name="android:paddingRight">16dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue