Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .skills/compose-ui/strings-index.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ import org.jetbrains.compose.resources.StringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.error
import org.meshtastic.core.resources.message_delivery_status
import org.meshtastic.core.resources.message_routing_error_admin_bad_session_key
import org.meshtastic.core.resources.message_routing_error_admin_public_key_unauthorized
import org.meshtastic.core.resources.message_routing_error_bad_request
import org.meshtastic.core.resources.message_routing_error_duty_cycle_limit
import org.meshtastic.core.resources.message_routing_error_max_retransmit
import org.meshtastic.core.resources.message_routing_error_no_channel
import org.meshtastic.core.resources.message_routing_error_no_interface
import org.meshtastic.core.resources.message_routing_error_no_response
import org.meshtastic.core.resources.message_routing_error_not_authorized
import org.meshtastic.core.resources.message_routing_error_pki_failed
import org.meshtastic.core.resources.message_routing_error_pki_send_fail_public_key
import org.meshtastic.core.resources.message_routing_error_pki_unknown_pubkey
import org.meshtastic.core.resources.message_routing_error_rate_limit_exceeded
import org.meshtastic.core.resources.message_routing_error_too_large
import org.meshtastic.core.resources.message_status_delivered
import org.meshtastic.core.resources.message_status_enroute
Expand Down Expand Up @@ -78,23 +86,40 @@ fun getStringResFrom(routingError: Int): StringResource = when (routingError) {
else -> Res.string.unrecognized
}

@Suppress("CyclomaticComplexMethod")
fun getMessageRoutingErrorStringResFrom(routingError: Int): StringResource = when (routingError) {
Routing.Error.GOT_NAK.value,
Routing.Error.TIMEOUT.value,
Routing.Error.MAX_RETRANSMIT.value,
Routing.Error.NO_RESPONSE.value,
-> Res.string.message_routing_error_max_retransmit

Routing.Error.NO_CHANNEL.value -> Res.string.message_routing_error_no_channel

Routing.Error.NO_INTERFACE.value -> Res.string.message_routing_error_no_interface

Routing.Error.DUTY_CYCLE_LIMIT.value -> Res.string.message_routing_error_duty_cycle_limit

Routing.Error.RATE_LIMIT_EXCEEDED.value -> Res.string.message_routing_error_rate_limit_exceeded

Routing.Error.TOO_LARGE.value -> Res.string.message_routing_error_too_large

Routing.Error.NO_RESPONSE.value -> Res.string.message_routing_error_no_response

Routing.Error.BAD_REQUEST.value -> Res.string.message_routing_error_bad_request

Routing.Error.NOT_AUTHORIZED.value -> Res.string.message_routing_error_not_authorized

Routing.Error.PKI_FAILED.value -> Res.string.message_routing_error_pki_failed

Routing.Error.PKI_UNKNOWN_PUBKEY.value -> Res.string.message_routing_error_pki_unknown_pubkey

Routing.Error.PKI_SEND_FAIL_PUBLIC_KEY.value -> Res.string.message_routing_error_pki_send_fail_public_key

Routing.Error.ADMIN_BAD_SESSION_KEY.value -> Res.string.message_routing_error_admin_bad_session_key

Routing.Error.ADMIN_PUBLIC_KEY_UNAUTHORIZED.value ->
Res.string.message_routing_error_admin_public_key_unauthorized

else -> getStringResFrom(routingError)
}

Expand Down Expand Up @@ -140,7 +165,7 @@ fun isMessageStatusRetryable(status: MessageStatus?, routingError: Int, isDirect
else -> true
}

private val nonRetryableMessageRoutingErrors = setOf(Routing.Error.NO_CHANNEL.value, Routing.Error.TOO_LARGE.value)
private val nonRetryableMessageRoutingErrors = setOf(Routing.Error.TOO_LARGE.value)

data class Message(
val uuid: Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,40 @@ import okio.ByteString.Companion.encodeUtf8
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.error
import org.meshtastic.core.resources.message_delivery_status
import org.meshtastic.core.resources.message_routing_error_admin_bad_session_key
import org.meshtastic.core.resources.message_routing_error_admin_public_key_unauthorized
import org.meshtastic.core.resources.message_routing_error_bad_request
import org.meshtastic.core.resources.message_routing_error_duty_cycle_limit
import org.meshtastic.core.resources.message_routing_error_max_retransmit
import org.meshtastic.core.resources.message_routing_error_no_channel
import org.meshtastic.core.resources.message_routing_error_no_interface
import org.meshtastic.core.resources.message_routing_error_no_response
import org.meshtastic.core.resources.message_routing_error_not_authorized
import org.meshtastic.core.resources.message_routing_error_pki_failed
import org.meshtastic.core.resources.message_routing_error_pki_send_fail_public_key
import org.meshtastic.core.resources.message_routing_error_pki_unknown_pubkey
import org.meshtastic.core.resources.message_routing_error_rate_limit_exceeded
import org.meshtastic.core.resources.message_routing_error_too_large
import org.meshtastic.core.resources.message_status_delivered
import org.meshtastic.core.resources.message_status_enroute
import org.meshtastic.core.resources.message_status_recipient_delivered
import org.meshtastic.core.resources.message_status_relayed_not_confirmed
import org.meshtastic.core.resources.message_status_unknown
import org.meshtastic.core.resources.routing_error_admin_bad_session_key
import org.meshtastic.core.resources.routing_error_admin_public_key_unauthorized
import org.meshtastic.core.resources.routing_error_bad_request
import org.meshtastic.core.resources.routing_error_duty_cycle_limit
import org.meshtastic.core.resources.routing_error_max_retransmit
import org.meshtastic.core.resources.routing_error_no_channel
import org.meshtastic.core.resources.routing_error_no_interface
import org.meshtastic.core.resources.routing_error_no_response
import org.meshtastic.core.resources.routing_error_no_route
import org.meshtastic.core.resources.routing_error_none
import org.meshtastic.core.resources.routing_error_not_authorized
import org.meshtastic.core.resources.routing_error_pki_failed
import org.meshtastic.core.resources.routing_error_pki_send_fail_public_key
import org.meshtastic.core.resources.routing_error_pki_unknown_pubkey
import org.meshtastic.core.resources.routing_error_rate_limit_exceeded
import org.meshtastic.core.resources.routing_error_too_large
import org.meshtastic.core.resources.unrecognized
import org.meshtastic.proto.PortNum
Expand Down Expand Up @@ -309,13 +325,21 @@ class MessageTest {
Routing.Error.MAX_RETRANSMIT.value to Res.string.message_routing_error_max_retransmit,
Routing.Error.GOT_NAK.value to Res.string.message_routing_error_max_retransmit,
Routing.Error.TIMEOUT.value to Res.string.message_routing_error_max_retransmit,
Routing.Error.NO_RESPONSE.value to Res.string.message_routing_error_max_retransmit,
Routing.Error.NO_CHANNEL.value to Res.string.message_routing_error_no_channel,
Routing.Error.NO_INTERFACE.value to Res.string.message_routing_error_no_interface,
Routing.Error.DUTY_CYCLE_LIMIT.value to Res.string.message_routing_error_duty_cycle_limit,
Routing.Error.RATE_LIMIT_EXCEEDED.value to Res.string.message_routing_error_rate_limit_exceeded,
Routing.Error.NO_RESPONSE.value to Res.string.message_routing_error_no_response,
Routing.Error.BAD_REQUEST.value to Res.string.message_routing_error_bad_request,
Routing.Error.NOT_AUTHORIZED.value to Res.string.message_routing_error_not_authorized,
Routing.Error.PKI_FAILED.value to Res.string.message_routing_error_pki_failed,
Routing.Error.PKI_SEND_FAIL_PUBLIC_KEY.value to
Res.string.message_routing_error_pki_send_fail_public_key,
Routing.Error.PKI_UNKNOWN_PUBKEY.value to Res.string.message_routing_error_pki_unknown_pubkey,
Routing.Error.TOO_LARGE.value to Res.string.message_routing_error_too_large,
Routing.Error.ADMIN_BAD_SESSION_KEY.value to Res.string.message_routing_error_admin_bad_session_key,
Routing.Error.ADMIN_PUBLIC_KEY_UNAUTHORIZED.value to
Res.string.message_routing_error_admin_public_key_unauthorized,
)

for ((routingError, expectedText) in mappings) {
Expand Down Expand Up @@ -366,10 +390,19 @@ class MessageTest {
listOf(
Routing.Error.MAX_RETRANSMIT.value to Res.string.routing_error_max_retransmit,
Routing.Error.NO_CHANNEL.value to Res.string.routing_error_no_channel,
Routing.Error.NO_INTERFACE.value to Res.string.routing_error_no_interface,
Routing.Error.DUTY_CYCLE_LIMIT.value to Res.string.routing_error_duty_cycle_limit,
Routing.Error.RATE_LIMIT_EXCEEDED.value to Res.string.routing_error_rate_limit_exceeded,
Routing.Error.NO_RESPONSE.value to Res.string.routing_error_no_response,
Routing.Error.BAD_REQUEST.value to Res.string.routing_error_bad_request,
Routing.Error.NOT_AUTHORIZED.value to Res.string.routing_error_not_authorized,
Routing.Error.PKI_FAILED.value to Res.string.routing_error_pki_failed,
Routing.Error.PKI_SEND_FAIL_PUBLIC_KEY.value to Res.string.routing_error_pki_send_fail_public_key,
Routing.Error.PKI_UNKNOWN_PUBKEY.value to Res.string.routing_error_pki_unknown_pubkey,
Routing.Error.TOO_LARGE.value to Res.string.routing_error_too_large,
Routing.Error.ADMIN_BAD_SESSION_KEY.value to Res.string.routing_error_admin_bad_session_key,
Routing.Error.ADMIN_PUBLIC_KEY_UNAUTHORIZED.value to
Res.string.routing_error_admin_public_key_unauthorized,
)

for ((routingError, expectedText) in mappings) {
Expand All @@ -385,17 +418,26 @@ class MessageTest {
)
val retryableRoutingErrors =
listOf(
Routing.Error.NO_INTERFACE.value,
Routing.Error.NO_RESPONSE.value,
Routing.Error.NO_CHANNEL.value,
Routing.Error.BAD_REQUEST.value,
Routing.Error.NOT_AUTHORIZED.value,
Routing.Error.DUTY_CYCLE_LIMIT.value,
Routing.Error.PKI_FAILED.value,
Routing.Error.PKI_SEND_FAIL_PUBLIC_KEY.value,
Routing.Error.PKI_UNKNOWN_PUBKEY.value,
Routing.Error.ADMIN_BAD_SESSION_KEY.value,
Routing.Error.ADMIN_PUBLIC_KEY_UNAUTHORIZED.value,
Routing.Error.RATE_LIMIT_EXCEEDED.value,
)

for (routingError in retryableRoutingErrors) {
assertTrue(messageWith(status = MessageStatus.ERROR, routingError = routingError).isStatusRetryable())
}
assertTrue(messageWith(status = MessageStatus.DELIVERED).isStatusRetryable(isDirectMessage = true))

val nonRetryableRoutingErrors = listOf(Routing.Error.NO_CHANNEL.value, Routing.Error.TOO_LARGE.value)
val nonRetryableRoutingErrors = listOf(Routing.Error.TOO_LARGE.value)

for (routingError in nonRetryableRoutingErrors) {
assertFalse(messageWith(status = MessageStatus.ERROR, routingError = routingError).isStatusRetryable())
Expand Down
38 changes: 23 additions & 15 deletions core/resources/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -990,11 +990,19 @@
<string name="message_delivery_status">Message delivery status</string>
<string name="message_device_managed">This radio is managed and can only be changed by a remote admin.</string>
<string name="message_input_label">Message</string>
<string name="message_routing_error_admin_bad_session_key">Admin session expired</string>
<string name="message_routing_error_admin_public_key_unauthorized">Admin key not authorized</string>
<string name="message_routing_error_bad_request">Invalid request</string>
<string name="message_routing_error_duty_cycle_limit">Duty cycle limit</string>
<string name="message_routing_error_max_retransmit">Failed to deliver to mesh</string>
<string name="message_routing_error_no_channel">No channel selected</string>
<string name="message_routing_error_no_channel">Channel/key mismatch</string>
<string name="message_routing_error_no_interface">No radio interface</string>
<string name="message_routing_error_no_response">No app response</string>
<string name="message_routing_error_not_authorized">Not authorized</string>
<string name="message_routing_error_pki_failed">Could not send encrypted message</string>
<string name="message_routing_error_pki_send_fail_public_key">Recipient key unavailable</string>
<string name="message_routing_error_pki_unknown_pubkey">Recipient needs your key</string>
<string name="message_routing_error_rate_limit_exceeded">Rate limited</string>
<string name="message_routing_error_too_large">Message is too large to send</string>
<string name="message_status_delivered">Delivered to mesh</string>
<string name="message_status_enroute">Sending...</string>
Expand Down Expand Up @@ -1373,24 +1381,24 @@
<string name="rotary_encoder_1_enabled">Rotary encoder #1 enabled</string>
<string name="router_role_confirmation_text">I have read the &lt;a href="https://meshtastic.org/docs/configuration/radio/device/#roles"&gt;Device Role Documentation&lt;/a&gt; and the blog post about &lt;a href="http://meshtastic.org/blog/choosing-the-right-device-role"&gt;Choosing The Right Device Role&lt;/a&gt;.</string>
<!-- ROUTING -->
<string name="routing_error_admin_bad_session_key">Bad session key</string>
<string name="routing_error_admin_public_key_unauthorized">Public Key unauthorized</string>
<string name="routing_error_bad_request">Bad Request</string>
<string name="routing_error_duty_cycle_limit">Regional Duty Cycle Limit Reached</string>
<string name="routing_error_admin_bad_session_key">Admin session expired</string>
<string name="routing_error_admin_public_key_unauthorized">Admin key not authorized</string>
<string name="routing_error_bad_request">Invalid request</string>
<string name="routing_error_duty_cycle_limit">Duty cycle limit</string>
<string name="routing_error_got_nak">Received a negative acknowledgment</string>
<string name="routing_error_max_retransmit">Max Retransmission Reached</string>
<string name="routing_error_no_channel">No Channel</string>
<string name="routing_error_no_interface">No Interface</string>
<string name="routing_error_no_response">No response</string>
<string name="routing_error_max_retransmit">Failed to deliver to mesh</string>
<string name="routing_error_no_channel">Channel/key mismatch</string>
<string name="routing_error_no_interface">No radio interface</string>
<string name="routing_error_no_response">No app response</string>
<string name="routing_error_no_route">No route</string>
<string name="routing_error_none">Acknowledged</string>
<string name="routing_error_not_authorized">Not Authorized</string>
<string name="routing_error_pki_failed">Encrypted Send Failed</string>
<string name="routing_error_pki_send_fail_public_key">PKI send failed, no public key</string>
<string name="routing_error_pki_unknown_pubkey">Unknown Public Key</string>
<string name="routing_error_rate_limit_exceeded">Rate Limit Exceeded. Please try again later.</string>
<string name="routing_error_not_authorized">Not authorized</string>
<string name="routing_error_pki_failed">Could not send encrypted message</string>
<string name="routing_error_pki_send_fail_public_key">Recipient key unavailable</string>
<string name="routing_error_pki_unknown_pubkey">Recipient needs your key</string>
<string name="routing_error_rate_limit_exceeded">Rate limited</string>
<string name="routing_error_timeout">Timeout</string>
<string name="routing_error_too_large">Packet too large</string>
<string name="routing_error_too_large">Message is too large to send</string>
<string name="rssi">RSSI</string>
<string name="rssi_definition">Received Signal Strength Indicator, a measurement used to determine the power level being received by the antenna. A higher RSSI value generally indicates a stronger and more stable connection.</string>
<string name="rsyslog_server">rsyslog server</string>
Expand Down
8 changes: 4 additions & 4 deletions docs/ar-rSA/user/messages-and-channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ When a message fails to deliver, the error indicator shows what went wrong:
| Got NAK | The next-hop node refused to relay | The relay node may be congested. Wait and retry. |
| استغرق وقت طويل | No acknowledgment within retry window | The recipient may be just out of range. Try increasing hop limit or moving to a better position. |
| لم يجد وسيط | No radio interface available to send | Check that your radio is connected and the channel is configured. |
| Max Retransmit | All retry attempts exhausted | The mesh path is unreliable. Try a different channel or wait for conditions to improve. |
| Failed to deliver to mesh | All retry attempts exhausted | Move closer, improve signal, or wait for mesh conditions to improve. |
| لا يوجد قناه | The destination channel doesn't exist | Verify both nodes share the same channel configuration. |
| Too Large | Message exceeds maximum payload size | Shorten your message (max ~200 characters). |
| No Response | Node received message but didn't respond | The recipient's radio may be busy or in low-power sleep mode. |
| Duty Cycle Limit | Regional airtime limit reached | Your radio has used its allowed transmit time. Wait for the duty cycle window to reset (typically 1 hour in EU regions). |
| Message is too large to send | Message exceeds maximum payload size | Shorten the message and try again. |
| No app response | App or plugin did not respond to the request | Retry or check the destination app or module state. |
| Duty cycle limit | Regional airtime limit reached | Wait for the duty cycle window to reset. |
| طلب غير جيد | Malformed or invalid message | This usually indicates a software bug. Try restarting the app. |

> 💡 **Tip:** Most delivery errors resolve themselves. If a node is intermittently reachable, the mesh will retry. For persistent "No Route" errors, check that intermediate Router nodes are online.
Expand Down
Loading
Loading