diff --git a/app/src/main/java/com/geeksville/mesh/service/Constants.kt b/app/src/main/java/com/geeksville/mesh/service/Constants.kt index 36c48add3..f350d6c28 100644 --- a/app/src/main/java/com/geeksville/mesh/service/Constants.kt +++ b/app/src/main/java/com/geeksville/mesh/service/Constants.kt @@ -16,22 +16,24 @@ */ package com.geeksville.mesh.service +import org.meshtastic.core.api.MeshtasticIntent + const val PREFIX = "com.geeksville.mesh" -const val ACTION_NODE_CHANGE = "$PREFIX.NODE_CHANGE" -const val ACTION_MESH_CONNECTED = "$PREFIX.MESH_CONNECTED" -const val ACTION_MESH_DISCONNECTED = "$PREFIX.MESH_DISCONNECTED" -const val ACTION_CONNECTION_CHANGED = "$PREFIX.CONNECTION_CHANGED" -const val ACTION_MESSAGE_STATUS = "$PREFIX.MESSAGE_STATUS" +const val ACTION_NODE_CHANGE = MeshtasticIntent.ACTION_NODE_CHANGE +const val ACTION_MESH_CONNECTED = MeshtasticIntent.ACTION_MESH_CONNECTED +const val ACTION_MESH_DISCONNECTED = MeshtasticIntent.ACTION_MESH_DISCONNECTED +const val ACTION_CONNECTION_CHANGED = MeshtasticIntent.ACTION_CONNECTION_CHANGED +const val ACTION_MESSAGE_STATUS = MeshtasticIntent.ACTION_MESSAGE_STATUS -const val ACTION_RECEIVED_TEXT_MESSAGE_APP = "$PREFIX.RECEIVED.TEXT_MESSAGE_APP" -const val ACTION_RECEIVED_POSITION_APP = "$PREFIX.RECEIVED.POSITION_APP" -const val ACTION_RECEIVED_NODEINFO_APP = "$PREFIX.RECEIVED.NODEINFO_APP" -const val ACTION_RECEIVED_TELEMETRY_APP = "$PREFIX.RECEIVED.TELEMETRY_APP" -const val ACTION_RECEIVED_ATAK_PLUGIN = "$PREFIX.RECEIVED.ATAK_PLUGIN" -const val ACTION_RECEIVED_ATAK_FORWARDER = "$PREFIX.RECEIVED.ATAK_FORWARDER" -const val ACTION_RECEIVED_DETECTION_SENSOR_APP = "$PREFIX.RECEIVED.DETECTION_SENSOR_APP" -const val ACTION_RECEIVED_PRIVATE_APP = "$PREFIX.RECEIVED.PRIVATE_APP" +const val ACTION_RECEIVED_TEXT_MESSAGE_APP = MeshtasticIntent.ACTION_RECEIVED_TEXT_MESSAGE_APP +const val ACTION_RECEIVED_POSITION_APP = MeshtasticIntent.ACTION_RECEIVED_POSITION_APP +const val ACTION_RECEIVED_NODEINFO_APP = MeshtasticIntent.ACTION_RECEIVED_NODEINFO_APP +const val ACTION_RECEIVED_TELEMETRY_APP = MeshtasticIntent.ACTION_RECEIVED_TELEMETRY_APP +const val ACTION_RECEIVED_ATAK_PLUGIN = MeshtasticIntent.ACTION_RECEIVED_ATAK_PLUGIN +const val ACTION_RECEIVED_ATAK_FORWARDER = MeshtasticIntent.ACTION_RECEIVED_ATAK_FORWARDER +const val ACTION_RECEIVED_DETECTION_SENSOR_APP = MeshtasticIntent.ACTION_RECEIVED_DETECTION_SENSOR_APP +const val ACTION_RECEIVED_PRIVATE_APP = MeshtasticIntent.ACTION_RECEIVED_PRIVATE_APP fun actionReceived(portNum: String) = "$PREFIX.RECEIVED.$portNum" @@ -39,14 +41,11 @@ fun actionReceived(portNum: String) = "$PREFIX.RECEIVED.$portNum" // standard EXTRA bundle definitions // -// a bool true means now connected, false means not -const val EXTRA_CONNECTED = "$PREFIX.Connected" +const val EXTRA_CONNECTED = MeshtasticIntent.EXTRA_CONNECTED const val EXTRA_PROGRESS = "$PREFIX.Progress" - -// / a bool true means we expect this condition to continue until, false means device might come back const val EXTRA_PERMANENT = "$PREFIX.Permanent" -const val EXTRA_PAYLOAD = "$PREFIX.Payload" -const val EXTRA_NODEINFO = "$PREFIX.NodeInfo" -const val EXTRA_PACKET_ID = "$PREFIX.PacketId" -const val EXTRA_STATUS = "$PREFIX.Status" +const val EXTRA_PAYLOAD = MeshtasticIntent.EXTRA_PAYLOAD +const val EXTRA_NODEINFO = MeshtasticIntent.EXTRA_NODEINFO +const val EXTRA_PACKET_ID = MeshtasticIntent.EXTRA_PACKET_ID +const val EXTRA_STATUS = MeshtasticIntent.EXTRA_STATUS diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshDataHandler.kt b/app/src/main/java/com/geeksville/mesh/service/MeshDataHandler.kt index be63802bf..4a3589b44 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshDataHandler.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshDataHandler.kt @@ -137,7 +137,9 @@ constructor( PortNum.POSITION_APP -> handlePosition(packet, dataPacket, myNodeNum) PortNum.NODEINFO_APP -> if (!fromUs) handleNodeInfo(packet) PortNum.TELEMETRY_APP -> handleTelemetry(packet, dataPacket, myNodeNum) - else -> shouldBroadcast = handleSpecializedDataPacket(packet, dataPacket, myNodeNum, logUuid, logInsertJob) + else -> + shouldBroadcast = + handleSpecializedDataPacket(packet, dataPacket, myNodeNum, fromUs, logUuid, logInsertJob) } return shouldBroadcast } @@ -146,14 +148,16 @@ constructor( packet: MeshPacket, dataPacket: DataPacket, myNodeNum: Int, + fromUs: Boolean, logUuid: String?, logInsertJob: Job?, ): Boolean { - var shouldBroadcast = false + var shouldBroadcast = !fromUs val decoded = packet.decoded ?: return shouldBroadcast when (decoded.portnum) { PortNum.TRACEROUTE_APP -> { tracerouteHandler.handleTraceroute(packet, logUuid, logInsertJob) + shouldBroadcast = false } PortNum.ROUTING_APP -> { handleRouting(packet, dataPacket) diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshServiceBroadcasts.kt b/app/src/main/java/com/geeksville/mesh/service/MeshServiceBroadcasts.kt index 14f9da3c7..e0215bc15 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshServiceBroadcasts.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshServiceBroadcasts.kt @@ -113,7 +113,7 @@ constructor( * NODE_CHANGE for new IDs appearing or disappearing * ACTION_MESH_CONNECTED for losing/gaining connection to the packet radio * Note: this is not the same as RadioInterfaceService.RADIO_CONNECTED_ACTION, - * because it implies we have assembled a warehouse valid node db. + * because it implies we have assembled a valid node db. */ private fun explicitBroadcast(intent: Intent) { context.sendBroadcast( diff --git a/core/api/src/main/kotlin/org/meshtastic/core/api/MeshtasticIntent.kt b/core/api/src/main/kotlin/org/meshtastic/core/api/MeshtasticIntent.kt new file mode 100644 index 000000000..f0c59993f --- /dev/null +++ b/core/api/src/main/kotlin/org/meshtastic/core/api/MeshtasticIntent.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025-2026 Meshtastic LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.meshtastic.core.api + +import org.meshtastic.core.api.MeshtasticIntent.EXTRA_CONNECTED +import org.meshtastic.core.api.MeshtasticIntent.EXTRA_NODEINFO +import org.meshtastic.core.api.MeshtasticIntent.EXTRA_PACKET_ID +import org.meshtastic.core.api.MeshtasticIntent.EXTRA_STATUS + + +/** + * Constants for Meshtastic Android Intents. These are used by external applications to communicate with the Meshtastic + * service. + */ +object MeshtasticIntent { + private const val PREFIX = "com.geeksville.mesh" + + /** Broadcast when a node's information changes. Extra: [EXTRA_NODEINFO] */ + const val ACTION_NODE_CHANGE = "$PREFIX.NODE_CHANGE" + + /** Broadcast when the mesh radio connects. Extra: [EXTRA_CONNECTED] */ + const val ACTION_MESH_CONNECTED = "$PREFIX.MESH_CONNECTED" + + /** Broadcast when the mesh radio disconnects. */ + const val ACTION_MESH_DISCONNECTED = "$PREFIX.MESH_DISCONNECTED" + + /** Legacy broadcast for connection changes. Extra: [EXTRA_CONNECTED] */ + const val ACTION_CONNECTION_CHANGED = "$PREFIX.CONNECTION_CHANGED" + + /** Broadcast for message status updates. Extras: [EXTRA_PACKET_ID], [EXTRA_STATUS] */ + const val ACTION_MESSAGE_STATUS = "$PREFIX.MESSAGE_STATUS" + + /** Received a text message. */ + const val ACTION_RECEIVED_TEXT_MESSAGE_APP = "$PREFIX.RECEIVED.TEXT_MESSAGE_APP" + + /** Received a position update. */ + const val ACTION_RECEIVED_POSITION_APP = "$PREFIX.RECEIVED.POSITION_APP" + + /** Received node info. */ + const val ACTION_RECEIVED_NODEINFO_APP = "$PREFIX.RECEIVED.NODEINFO_APP" + + /** Received telemetry data. */ + const val ACTION_RECEIVED_TELEMETRY_APP = "$PREFIX.RECEIVED.TELEMETRY_APP" + + /** Received ATAK Plugin data. */ + const val ACTION_RECEIVED_ATAK_PLUGIN = "$PREFIX.RECEIVED.ATAK_PLUGIN" + + /** Received ATAK Forwarder data. */ + const val ACTION_RECEIVED_ATAK_FORWARDER = "$PREFIX.RECEIVED.ATAK_FORWARDER" + + /** Received detection sensor data. */ + const val ACTION_RECEIVED_DETECTION_SENSOR_APP = "$PREFIX.RECEIVED.DETECTION_SENSOR_APP" + + /** Received private app data. */ + const val ACTION_RECEIVED_PRIVATE_APP = "$PREFIX.RECEIVED.PRIVATE_APP" + + // standard EXTRA bundle definitions + const val EXTRA_CONNECTED = "$PREFIX.Connected" + const val EXTRA_PAYLOAD = "$PREFIX.Payload" + const val EXTRA_NODEINFO = "$PREFIX.NodeInfo" + const val EXTRA_PACKET_ID = "$PREFIX.PacketId" + const val EXTRA_STATUS = "$PREFIX.Status" +} diff --git a/mesh_service_example/src/main/kotlin/com/meshtastic/android/meshserviceexample/MainActivity.kt b/mesh_service_example/src/main/kotlin/com/meshtastic/android/meshserviceexample/MainActivity.kt index 5c8376686..c558de7e8 100644 --- a/mesh_service_example/src/main/kotlin/com/meshtastic/android/meshserviceexample/MainActivity.kt +++ b/mesh_service_example/src/main/kotlin/com/meshtastic/android/meshserviceexample/MainActivity.kt @@ -39,6 +39,7 @@ import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext +import org.meshtastic.core.api.MeshtasticIntent import org.meshtastic.core.service.IMeshService private const val TAG: String = "MeshServiceExample" @@ -83,19 +84,19 @@ class MainActivity : ComponentActivity() { val intentFilter = IntentFilter().apply { - addAction("com.geeksville.mesh.NODE_CHANGE") - addAction("com.geeksville.mesh.CONNECTION_CHANGED") - addAction("com.geeksville.mesh.MESH_CONNECTED") - addAction("com.geeksville.mesh.MESH_DISCONNECTED") - addAction("com.geeksville.mesh.MESSAGE_STATUS") - addAction("com.geeksville.mesh.RECEIVED.TEXT_MESSAGE_APP") - addAction("com.geeksville.mesh.RECEIVED.POSITION_APP") - addAction("com.geeksville.mesh.RECEIVED.TELEMETRY_APP") - addAction("com.geeksville.mesh.RECEIVED.NODEINFO_APP") - addAction("com.geeksville.mesh.RECEIVED.ATAK_PLUGIN") - addAction("com.geeksville.mesh.RECEIVED.ATAK_FORWARDER") - addAction("com.geeksville.mesh.RECEIVED.DETECTION_SENSOR_APP") - addAction("com.geeksville.mesh.RECEIVED.PRIVATE_APP") + addAction(MeshtasticIntent.ACTION_NODE_CHANGE) + addAction(MeshtasticIntent.ACTION_CONNECTION_CHANGED) + addAction(MeshtasticIntent.ACTION_MESH_CONNECTED) + addAction(MeshtasticIntent.ACTION_MESH_DISCONNECTED) + addAction(MeshtasticIntent.ACTION_MESSAGE_STATUS) + addAction(MeshtasticIntent.ACTION_RECEIVED_TEXT_MESSAGE_APP) + addAction(MeshtasticIntent.ACTION_RECEIVED_POSITION_APP) + addAction(MeshtasticIntent.ACTION_RECEIVED_TELEMETRY_APP) + addAction(MeshtasticIntent.ACTION_RECEIVED_NODEINFO_APP) + addAction(MeshtasticIntent.ACTION_RECEIVED_ATAK_PLUGIN) + addAction(MeshtasticIntent.ACTION_RECEIVED_ATAK_FORWARDER) + addAction(MeshtasticIntent.ACTION_RECEIVED_DETECTION_SENSOR_APP) + addAction(MeshtasticIntent.ACTION_RECEIVED_PRIVATE_APP) } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {