|
| 1 | +/* |
| 2 | + * Copyright (c) 2026 Meshtastic LLC |
| 3 | + * |
| 4 | + * This program is free software: you can redistribute it and/or modify |
| 5 | + * it under the terms of the GNU General Public License as published by |
| 6 | + * the Free Software Foundation, either version 3 of the License, or |
| 7 | + * (at your option) any later version. |
| 8 | + * |
| 9 | + * This program is distributed in the hope that it will be useful, |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | + * GNU General Public License for more details. |
| 13 | + * |
| 14 | + * You should have received a copy of the GNU General Public License |
| 15 | + * along with this program. If not, see <https://www.gnu.org/licenses/>. |
| 16 | + */ |
| 17 | +package org.meshtastic.app.ai.appfunctions |
| 18 | + |
| 19 | +import androidx.appfunctions.AppFunctionIntValueConstraint |
| 20 | +import androidx.appfunctions.AppFunctionSerializable |
| 21 | +import androidx.appfunctions.AppFunctionStringValueConstraint |
| 22 | + |
| 23 | +/** Response returned when a message is successfully sent via the mesh network. */ |
| 24 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 25 | +data class SendMessageResponse( |
| 26 | + /** The identifier assigned to the outgoing message. */ |
| 27 | + val messageId: Int, |
| 28 | + /** The channel or destination the message was sent to. */ |
| 29 | + val channel: String, |
| 30 | + /** The time the message was sent (epoch milliseconds). */ |
| 31 | + val timestamp: Long, |
| 32 | +) |
| 33 | + |
| 34 | +/** Response containing the current status of the Meshtastic mesh network. */ |
| 35 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 36 | +data class MeshStatusResponse( |
| 37 | + /** The current radio connection state (e.g., CONNECTED, DISCONNECTED). */ |
| 38 | + @property:AppFunctionStringValueConstraint(enumValues = ["CONNECTED", "DISCONNECTED", "DEVICE_SLEEP"]) |
| 39 | + val connectionState: String, |
| 40 | + /** The number of nodes currently online (heard within the last 2 hours). */ |
| 41 | + val onlineNodeCount: Int, |
| 42 | + /** The total number of nodes known to the network. */ |
| 43 | + val totalNodeCount: Int, |
| 44 | + /** The battery percentage of the connected Meshtastic device (1-100), or null if unavailable. */ |
| 45 | + val localBatteryLevel: Int?, |
| 46 | + /** The display name of the local node, or null if not set. */ |
| 47 | + val localNodeName: String?, |
| 48 | +) |
| 49 | + |
| 50 | +/** Information about a single mesh node. */ |
| 51 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 52 | +data class NodeInfo( |
| 53 | + /** The unique node identifier in Meshtastic hex format (e.g., !abc12345). */ |
| 54 | + val id: String, |
| 55 | + /** The human-readable name of the node. */ |
| 56 | + val name: String, |
| 57 | + /** The node's battery percentage (0-100), or null if unavailable. */ |
| 58 | + val batteryLevel: Int?, |
| 59 | + /** The time this node was last heard from (epoch milliseconds). */ |
| 60 | + val lastHeard: Long, |
| 61 | + /** Whether this node is currently considered online. */ |
| 62 | + val isOnline: Boolean, |
| 63 | +) |
| 64 | + |
| 65 | +/** Response containing a list of nodes visible on the mesh network. */ |
| 66 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 67 | +data class GetNodeListResponse( |
| 68 | + /** List of nodes sorted by most recently heard first. */ |
| 69 | + val nodes: List<NodeInfo>, |
| 70 | +) |
| 71 | + |
| 72 | +/** Information about a single mesh channel. */ |
| 73 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 74 | +data class ChannelInfo( |
| 75 | + /** The channel index (0-7). */ |
| 76 | + @property:AppFunctionIntValueConstraint(enumValues = [0, 1, 2, 3, 4, 5, 6, 7]) val index: Int, |
| 77 | + /** The human-readable name of the channel. */ |
| 78 | + val name: String, |
| 79 | + /** Whether this is the primary/default channel. */ |
| 80 | + val isPrimary: Boolean, |
| 81 | + /** Whether uplink is enabled for this channel. */ |
| 82 | + val uplinkEnabled: Boolean, |
| 83 | + /** Whether downlink is enabled for this channel. */ |
| 84 | + val downlinkEnabled: Boolean, |
| 85 | +) |
| 86 | + |
| 87 | +/** Response containing the list of available mesh channels. */ |
| 88 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 89 | +data class GetChannelInfoResponse( |
| 90 | + /** List of all configured channels. */ |
| 91 | + val channels: List<ChannelInfo>, |
| 92 | +) |
| 93 | + |
| 94 | +/** Response containing the status of the local Meshtastic device. */ |
| 95 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 96 | +data class GetDeviceStatusResponse( |
| 97 | + /** The hardware model of the device (e.g., "Meshtastic nRF52840"). */ |
| 98 | + val model: String, |
| 99 | + /** The firmware version string. */ |
| 100 | + val firmwareVersion: String, |
| 101 | + /** The device battery percentage (0-100), or null if not battery-powered. */ |
| 102 | + val batteryLevel: Int?, |
| 103 | + /** The charging state (CHARGING, NOT_CHARGING, or UNKNOWN). */ |
| 104 | + @property:AppFunctionStringValueConstraint(enumValues = ["CHARGING", "NOT_CHARGING", "UNKNOWN"]) |
| 105 | + val chargingStatus: String, |
| 106 | + /** The display name of the device, or null if not set. */ |
| 107 | + val deviceName: String?, |
| 108 | + /** Whether the radio is currently active and connected. */ |
| 109 | + val isActive: Boolean, |
| 110 | +) |
| 111 | + |
| 112 | +/** Response containing detailed telemetry for a specific mesh node. */ |
| 113 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 114 | +data class GetNodeDetailsResponse( |
| 115 | + /** Node ID in hex format (e.g., "!abc12345"). */ |
| 116 | + val id: String, |
| 117 | + /** User ID string for this node. */ |
| 118 | + val userId: String, |
| 119 | + /** Display name of the node. */ |
| 120 | + val name: String, |
| 121 | + /** Battery percentage (0-100), or null if unavailable. */ |
| 122 | + val batteryLevel: Int?, |
| 123 | + /** Supply voltage in volts, or null if unavailable. */ |
| 124 | + val voltage: Float?, |
| 125 | + /** Hardware model string. */ |
| 126 | + val hardwareModel: String, |
| 127 | + /** Firmware version string. */ |
| 128 | + val firmwareVersion: String, |
| 129 | + /** Signal-to-noise ratio of strongest signal. */ |
| 130 | + val snr: Float, |
| 131 | + /** Received signal strength indicator in dB. */ |
| 132 | + val rssi: Int, |
| 133 | + /** Number of hops away from local node (-1 if unknown). */ |
| 134 | + val hopsAway: Int, |
| 135 | + /** Channel index this node is on. */ |
| 136 | + val channel: Int, |
| 137 | + /** Last heard timestamp (milliseconds since epoch). */ |
| 138 | + val lastHeard: Long, |
| 139 | + /** User role or device type. */ |
| 140 | + val userRole: String, |
| 141 | + /** Whether the user is licensed. */ |
| 142 | + val isLicensed: Boolean, |
| 143 | + /** Latitude in degrees, or null if unknown. */ |
| 144 | + val latitude: Double?, |
| 145 | + /** Longitude in degrees, or null if unknown. */ |
| 146 | + val longitude: Double?, |
| 147 | +) |
| 148 | + |
| 149 | +/** Response containing aggregate mesh network metrics. */ |
| 150 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 151 | +data class GetMeshMetricsResponse( |
| 152 | + /** Total number of known nodes. */ |
| 153 | + val totalNodeCount: Int, |
| 154 | + /** Number of nodes currently online. */ |
| 155 | + val onlineNodeCount: Int, |
| 156 | + /** Average battery level across mesh, or null if no data. */ |
| 157 | + val averageBatteryLevel: Int?, |
| 158 | + /** Estimated health score (0-100). */ |
| 159 | + val meshHealthScore: Int, |
| 160 | + /** Timestamp of most recent packet (ms since epoch). */ |
| 161 | + val mostRecentPacketTime: Long, |
| 162 | + /** Mesh uptime in seconds. */ |
| 163 | + val meshUptimeSeconds: Long, |
| 164 | + /** Channel utilization percentage, or null if unavailable. */ |
| 165 | + val channelUtilizationPercent: Int?, |
| 166 | +) |
| 167 | + |
| 168 | +/** Response containing recent messages from the mesh network. */ |
| 169 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 170 | +data class GetRecentMessagesResponse( |
| 171 | + /** List of recent messages ordered by most recent first. */ |
| 172 | + val messages: List<MessageInfo>, |
| 173 | +) |
| 174 | + |
| 175 | +/** Information about a single mesh message. */ |
| 176 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 177 | +data class MessageInfo( |
| 178 | + /** Display name of the message sender. */ |
| 179 | + val senderName: String, |
| 180 | + /** The message text content. */ |
| 181 | + val text: String, |
| 182 | + /** Name of the channel or contact the message belongs to. */ |
| 183 | + val contactName: String, |
| 184 | + /** Timestamp when the message was received (ms since epoch). */ |
| 185 | + val receivedTime: Long, |
| 186 | + /** True if this message was sent by the local user. */ |
| 187 | + val fromLocal: Boolean, |
| 188 | + /** True if this message has been read by the user. */ |
| 189 | + val read: Boolean, |
| 190 | +) |
| 191 | + |
| 192 | +/** Response containing a summary of unread messages across all contacts. */ |
| 193 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 194 | +data class GetUnreadSummaryResponse( |
| 195 | + /** Total number of unread messages across all non-muted contacts. */ |
| 196 | + val totalUnreadCount: Int, |
| 197 | + /** Per-contact breakdown of unread messages, sorted by most recent. */ |
| 198 | + val contacts: List<ContactUnreadInfo>, |
| 199 | +) |
| 200 | + |
| 201 | +/** Unread message details for a single contact or channel. */ |
| 202 | +@AppFunctionSerializable(isDescribedByKDoc = true) |
| 203 | +data class ContactUnreadInfo( |
| 204 | + /** Display name of the contact or channel. */ |
| 205 | + val name: String, |
| 206 | + /** Number of unread messages from this contact. */ |
| 207 | + val unreadCount: Int, |
| 208 | + /** Preview text of the most recent message (up to 100 chars), or null if unavailable. */ |
| 209 | + val lastMessagePreview: String?, |
| 210 | + /** Timestamp of the most recent message (ms since epoch), or null if unavailable. */ |
| 211 | + val lastMessageTime: Long?, |
| 212 | +) |
0 commit comments