mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
clean up protobufs with a bit of futureproofing for new packet types
This commit is contained in:
parent
94e0255325
commit
7fb0cabee8
4 changed files with 77 additions and 34 deletions
6
TODO.md
6
TODO.md
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
|
||||
* handle failures in onCharWrite, instead of logAssert - because they can happen if device goes away
|
||||
* use android service from Signal
|
||||
* DONE handle failures in onCharWrite, instead of logAssert - because they can happen if device goes away
|
||||
* make test implementation of android service (doesn't use bluetooth)
|
||||
* clean up sw update code in device side
|
||||
* DONE add broadcasters for use by signal (node changes and packet received)
|
||||
* make compose based access show mesh state
|
||||
* use android service from Signal
|
||||
* add real messaging code/protobufs
|
||||
* use https://codelabs.developers.google.com/codelabs/jetpack-compose-basics/#4 to show service state
|
||||
* connect to bluetooth device automatically using minimum power
|
||||
|
|
@ -35,7 +35,7 @@ Don't leave device discoverable. Don't let unpaired users do thing with device
|
|||
|
||||
* make analytics optional
|
||||
* possibly use finotes for analytics https://finotes.com/
|
||||
* also add a receiver that fires after a new update was installed from the play stoe
|
||||
* also add a receiver that fires after a new update was installed from the play stoe
|
||||
|
||||
# Done
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,10 @@ interface IMeshService {
|
|||
|
||||
/*
|
||||
Send an opaque packet to a specified node name
|
||||
|
||||
typ is defined in mesh.proto Data.Type. For now juse use 0 to mean opaque bytes.
|
||||
*/
|
||||
void sendOpaque(String destId, in byte[] payload);
|
||||
void sendOpaque(String destId, in byte[] payload, int typ);
|
||||
|
||||
/**
|
||||
Get the IDs of everyone on the mesh. You should also subscribe for NODE_CHANGE broadcasts.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.geeksville.android.Logging
|
|||
import com.geeksville.mesh.MeshProtos.MeshPacket
|
||||
import com.geeksville.mesh.MeshProtos.ToRadio
|
||||
import com.google.protobuf.ByteString
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
* Handles all the communication with android apps. Also keeps an internal model
|
||||
|
|
@ -115,9 +116,8 @@ class MeshService : Service(), Logging {
|
|||
private fun toNodeID(n: Int) = toNodeInfo(n).user?.id
|
||||
|
||||
/// given a nodenum, return a db entry - creating if necessary
|
||||
private
|
||||
|
||||
fun getOrCreateNodeInfo(n: Int) = nodeDBbyNodeNum.getOrPut(n) { -> NodeInfo(n) }
|
||||
private fun getOrCreateNodeInfo(n: Int) =
|
||||
nodeDBbyNodeNum.getOrPut(n) { -> NodeInfo(n) }
|
||||
|
||||
/// Map a userid to a node/ node num, or throw an exception if not found
|
||||
private fun toNodeInfo(id: String) = nodeDBbyID.getValue(id)
|
||||
|
|
@ -139,6 +139,38 @@ class MeshService : Service(), Logging {
|
|||
/// Generate a new mesh packet builder with our node as the sender, and the specified recipient
|
||||
private fun newMeshPacketTo(id: String) = newMeshPacketTo(toNodeNum(id))
|
||||
|
||||
/// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
private fun handleReceivedData(fromNum: Int, data: MeshProtos.Data) {
|
||||
val bytes = data.payload.toByteArray()
|
||||
val fromId = toNodeID(fromNum)
|
||||
|
||||
/// the sending node ID if possible, else just its number
|
||||
val fromString = fromId ?: fromId.toString()
|
||||
|
||||
when (data.typValue) {
|
||||
MeshProtos.Data.Type.SIMPLE_TEXT_VALUE ->
|
||||
warn(
|
||||
"TODO ignoring SIMPLE_TEXT from $fromString: ${bytes.toString(
|
||||
Charset.forName("UTF-8")
|
||||
)}"
|
||||
)
|
||||
|
||||
MeshProtos.Data.Type.CLEAR_READACK_VALUE ->
|
||||
warn(
|
||||
"TODO ignoring CLEAR_READACK from $fromString"
|
||||
)
|
||||
|
||||
MeshProtos.Data.Type.SIGNAL_OPAQUE_VALUE ->
|
||||
if (fromId == null)
|
||||
error("Ignoring opaque from $fromNum because we don't yet know its ID")
|
||||
else {
|
||||
debug("Received opaque from $fromId ${bytes.size}")
|
||||
broadcastReceivedOpaque(fromId, bytes)
|
||||
}
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
/// Update our model and resend as needed for a MeshPacket we just received from the radio
|
||||
private fun handleReceivedMeshPacket(packet: MeshPacket) {
|
||||
val fromNum = packet.from
|
||||
|
|
@ -162,19 +194,9 @@ class MeshService : Service(), Logging {
|
|||
updateNodeInfo(fromNum) {
|
||||
it.lastSeen = p.time.msecs
|
||||
}
|
||||
MeshProtos.SubPacket.TEXT_FIELD_NUMBER -> {
|
||||
debug("TODO Ignoring TEXT from $fromNum ${p.text.text}")
|
||||
}
|
||||
MeshProtos.SubPacket.OPAQUE_FIELD_NUMBER -> {
|
||||
val opaque = p.opaque.payload.toByteArray()
|
||||
val fromId = toNodeID(fromNum)
|
||||
if (fromId == null)
|
||||
error("Ignoring opaque from $fromNum because we don't yet know its ID")
|
||||
else {
|
||||
debug("Received opaque from $fromId ${opaque.size}")
|
||||
broadcastReceivedOpaque(fromId, opaque)
|
||||
}
|
||||
}
|
||||
MeshProtos.SubPacket.DATA_FIELD_NUMBER ->
|
||||
handleReceivedData(fromNum, p.data)
|
||||
|
||||
MeshProtos.SubPacket.USER_FIELD_NUMBER ->
|
||||
updateNodeInfo(fromNum) {
|
||||
it.user = MeshUser(p.user.id, p.user.longName, p.user.shortName)
|
||||
|
|
@ -195,6 +217,10 @@ class MeshService : Service(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleReceivedNodeInfo(info: MeshProtos.NodeInfo) {
|
||||
TODO()
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives messages from our BT radio service and processes them to update our model
|
||||
* and send to clients as needed.
|
||||
|
|
@ -206,7 +232,7 @@ class MeshService : Service(), Logging {
|
|||
info("Received from radio service: $proto")
|
||||
when (proto.variantCase.number) {
|
||||
MeshProtos.FromRadio.PACKET_FIELD_NUMBER -> handleReceivedMeshPacket(proto.packet)
|
||||
MeshProtos.FromRadio.NODE_INFO_FIELD_NUMBER -> TODO()
|
||||
MeshProtos.FromRadio.NODE_INFO_FIELD_NUMBER -> handleReceivedNodeInfo(proto.nodeInfo)
|
||||
else -> TODO("Unexpected FromRadio variant")
|
||||
}
|
||||
}
|
||||
|
|
@ -217,15 +243,16 @@ class MeshService : Service(), Logging {
|
|||
error("TODO setOwner $myId : $longName : $shortName")
|
||||
}
|
||||
|
||||
override fun sendOpaque(destId: String, payloadIn: ByteArray) {
|
||||
override fun sendOpaque(destId: String, payloadIn: ByteArray, typ: Int) {
|
||||
info("sendOpaque $destId <- ${payloadIn.size}")
|
||||
|
||||
// encapsulate our payload in the proper protobufs and fire it off
|
||||
val packet = newMeshPacketTo(destId).apply {
|
||||
payload = MeshProtos.MeshPayload.newBuilder().apply {
|
||||
addSubPackets(MeshProtos.SubPacket.newBuilder().apply {
|
||||
opaque = MeshProtos.Opaque.newBuilder().apply {
|
||||
payload = ByteString.copyFrom(payloadIn)
|
||||
data = MeshProtos.Data.newBuilder().also {
|
||||
it.typ = MeshProtos.Data.Type.SIGNAL_OPAQUE
|
||||
it.payload = ByteString.copyFrom(payloadIn)
|
||||
}.build()
|
||||
}.build())
|
||||
}.build()
|
||||
|
|
|
|||
|
|
@ -53,13 +53,28 @@ message Time {
|
|||
uint64 msecs = 1; // msecs since 1970
|
||||
}
|
||||
|
||||
// A message sent from a device outside of the mesh, in a form the mesh does not understand
|
||||
// i.e. a Signal app level message.
|
||||
message Opaque {
|
||||
bytes payload = 1;
|
||||
// a data message to forward to an external app
|
||||
message Data {
|
||||
enum Type {
|
||||
/// A message sent from a device outside of the mesh, in a form the mesh does not understand
|
||||
SIGNAL_OPAQUE = 0; // NOTE: This must be 0, because it is documented in IMeshService.aidl to be so
|
||||
|
||||
/// a simple UTF-8 text message, which even the little micros in the mesh can understand and show on their screen
|
||||
/// eventually in some circumstances even signal might send messages in this form (see below)
|
||||
SIMPLE_TEXT = 1;
|
||||
|
||||
/// a message receive acknowledgement, sent in cleartext - allows radio to show user that a message has been read by the recpient, optional
|
||||
CLEAR_READACK = 2;
|
||||
|
||||
/// Not yet used but eventually:
|
||||
/// SIGNAL_CLEAR_OPAQUE = 3; // Unencrypted at the signal level, relying on the radio crypt only (to keep size small), but contains Signal control data radios don't care about (or non ascii text)
|
||||
}
|
||||
|
||||
Type typ = 1; // required
|
||||
bytes payload = 2; // required
|
||||
}
|
||||
|
||||
// a simple text message, which even the little micros in the mesh can understand and show on their screen
|
||||
|
||||
message Text {
|
||||
string text = 1;
|
||||
}
|
||||
|
|
@ -87,11 +102,10 @@ message SubPacket {
|
|||
oneof variant {
|
||||
Position position = 1;
|
||||
Time time = 2;
|
||||
Text text = 3;
|
||||
Opaque opaque = 4;
|
||||
User user = 5;
|
||||
WantNodeNum want_node = 6;
|
||||
DenyNodeNum deny_node = 7;
|
||||
Data data = 3;
|
||||
User user = 4;
|
||||
WantNodeNum want_node = 5;
|
||||
DenyNodeNum deny_node = 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue