GithubHelp home page GithubHelp logo

paulmandal / atak-forwarder Goto Github PK

View Code? Open in Web Editor NEW
390.0 52.0 42.0 90.29 MB

Forwards packets to/from ATAK over an off-grid communication layer

License: MIT License

Java 91.77% Kotlin 4.92% AIDL 2.45% Shell 0.86%

atak-forwarder's Introduction

ATAK Forwarder

An ATAK plugin for forwarding CoT messages via a hardware layer. Currently supports Meshtastic devices.

Binaries signed for the Play Store version of ATAK are available here: Binaries

IMPORTANT NOTE: All configuration options / Tracker writing have been moved into ATAK's three button (kebab) menu under Settings > Tool Preferences > Specific Tool Preferences > ATAK Forwarder

Share Markers and PLI

Share Markers and PLI
Plugin Status Screen

Send Chat Messages

Chat Messages

Configurable Channel Settings / Share with QR

Channel Mode Selection
QR Channel Sharing

Use standalone Meshtastic devices as Trackers

Write to Tracker

Features

  • In-app device and channel management
  • Broadcast messages are sent to the channel (e.g. map markers, PLI)
  • Direct messages to other users (e.g. chat messages)
  • Support for Meshtastic devices without an ATAK EUD attached
  • Efficient comm. using libcotshrink -- can send approx 5 map markers or PLI per minute, or 2 chats, or 2.5 more complex markers
  • Typical msg sizes, PLI: ~190 bytes, simple shape ~200 bytes, complex shape ~250 bytes, ~380 bytes, group chat ~400 bytes
  • Filtering of repeated messages with a configurable TTL (e.g. to prevent auto-send markers from flooding)
  • Message queue with priority (chat = pli > markers)
  • Support for USB devices

Supported Versions

The plugin has been tested with these versions of the Meshtastic dependencies. If you run into issues try installing these versions of the Meshtastic software to resolve them.

Dependency Version
Meshtastic App 2.2.16
Meshtastic Firmware 2.2.16

To Do

  • Needs more real-world stability testing
  • Use Dagger 2
  • Get a proper CI setup going (GitHub Actions?)

Building the Plugin

The below instructions assume that you are cloning everything side-by-side in the same directory, so you should end up with a directory tree like:

workspace/
  |
  \--- Meshtastic-Android/
  |
  \--- AndroidTacticalAssaultKit-CIV/
  |
  \--- atak-forwarder/

Set Up Meshtastic

  • Flash your devices with the supported version of the Meshtastic Firmware from the table above
  • Install the Meshtastic App from the Play Store.
  • Open the Meshtastic App, click on the Settings (gear) icon on the right of the screen, then click the + icon, the app will ask for Bluetooh permissions, grant them.

Build + Install ATAK

ATAK requires that plugins be signed with a whitelisted signature. In order to run your own builds of the plugin you will need to have a copy of ATAK that is signed with the same key you are using to sign your plugin build.

  • Clone the ATAK-CIV repo: git clone [email protected]:deptofdefense/AndroidTacticalAssaultKit-CIV.git
  • Follow the commands in the .github/workflows files or the instructions in AndroidTacticalAssaultKit-CIV/BUILDING.md to build and install ATAK
    • Note: you will need to configure a signing key in the local.properties file

Build the ATAK Gradle Plugin

  • Go to the AndroidTacticalAssaultKit-CIV/atak-gradle-takdev directory
  • Run ./gradlew assemble

Build + Install ATAK Forwarder

  • Clone the ATAK Forwarder repo: git clone [email protected]:paulmandal/atak-forwarder.git
  • Copy the local.properties file that you created while you were building ATAK to the atak-forwarder directory
  • Edit local.properties and add this line, remember to update the path to your correct path: sdk.path=/path/to/your/AndroidTacticalAssaultKit-CIV/atak/ATAK/app/build/libs
  • Edit the app Run Configuration in atak-forwarder and set the Launch Options to Nothing
  • Build the atak-forwarder plugin and install it on your devices (note: the environment variable ATAK_VERSION can be used to override the target ATAK version found in app/build.gradle)

Setting up the Plugin

Setting up your Comm Device

  • In the Android Settings / Connected Devices or Bluetooth Settings tap Pair a new device
  • Pair with your Meshtastic device
  • Start ATAK, you should see a purple icon in the lower right corner of the screen
  • Tap on the three dots menu in the upper right corner of the ATAK screen
  • Tap on Settings
  • Tap on Tool Preferences
  • Tap on Specific Tool Preferences
  • Tap on ATAK Forwarder Preferences
  • Tap on Refresh Devices
  • Tap on Set Comm Device and pick your device from the list
  • Tap on Set Region and pick the region you are currently in
  • The red line through the icon in the lower right corner of the screen should disappear within about a minute

Setting up your Channel

We recommend using the Meshtastic App to manage channel settings, if you would like to use the Plugin to manage channel settings be sure to enable the "Plugin Manages Device" option at the bottom of the settings screen. If you are using Meshtastic to manage the device you do not need to follow the steps below.

  • In ATAK tap on the three dots menu in the upper right corner of the screen
  • Tap on Settings
  • Tap on Tool Preferences
  • Tap on Specific Tool Preferences
  • Tap on ATAK Forwarder Preferences
  • Scroll to Channel Name and tap on it to set your channel name, max length is 11 characters
  • Tap on Mode / Speed and pick a mode, try Short Range / Fast to start with
  • Tap on Generate PSK to generate a new pre-shared key to encrypt your channel with
  • Tap on Show QR to show a QR code with your channel's settings
  • On your other devices, go to the same Settings screen and then tap Scan QR to scan the channel settings
    • You should see notifications about "discovery broadcasts" once all devices are on the same channel, if you do not check the channel name, hash, and try clicking Broadcast Discovery in the plugin settings menu (click the @)
    • You should soon see map markers for each of your devices

Setting up a Tracker device

The ATAK Forwarder supports configuring Meshtastic devices that have a GPS but no phone controlling them to show up on the map with a configurable callsign, team, and icon. This can be useful for retrieving relay devices or use cases that only need to output location data (e.g. animal tracking)

  • Pair your extra Meshtastic devices with your phone as normal
  • In ATAK tap on the three dots menu in the upper right corner of the screen
  • Tap on Settings
  • Tap on Tool Preferences
  • Tap on Specific Tool Preferences
  • Tap on ATAK Forwarder Preferences
  • Scroll to Tracker and configure your Team, Role, and other settings
  • Click on Write to Device and pick your device from the dropdown, set a Callsign and click OK
  • You will see a small spinning progress bar appear on the screen, wait until it disappears before doing anything else with the plugin
  • After the spinning progress bar disappears check the devices channel on its LCD, if the channel is updated reset the device by pressing the reset button for a second or two
  • You should see your device appear on the map after it boots back up, its location should start updating once it has a GPS lock

Notes on Message Handling

Message handling follows a few simple rules:

  • Messages from ATAK that are not chat are checked against a Recently Sent cache, if a message was recently sent it was dropped. This prevents spamming of auto-send map markers.

  • Messages are then queued in a prioritized queue, with the priority: chat = pli > marker

  • If a similar message already exists in the queue (e.g. PLI) it will be overwritten with the new message, this way a queued PLI won't be sent with out of date data if newer data is available

  • Messages are fetched from this queue by the CommHardware class and sent

  • The plugin will attempt to first use a "minimal" protobuf that saves space, but if it will result in dropped fields or a failed mapping on the receiving size it will fall back to the regular protobufs

  • When values appear more than once in a payload we attempt to replace subsequent appearances with a marker/placeholder that is swapped back for the value when rebuilding the original message

Contributing

Areas I'd especially like help are:

  • reducing the message sizes without affecting features in ATAK (e.g. removing detail.contact.endpoint kills chat) -- check out https://github.com/paulmandal/libcotshrink for this effort
  • increasing resilience of this plugin, it is basically fire-and-forget (and maybe lose your message) right now

atak-forwarder's People

Contributors

a-f-g-u-c avatar paulmandal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

atak-forwarder's Issues

ATAK not installing ATAK-forwarder plugin, never receives android.intent.action.PACKAGE_ADDED

On my Samsung S20 FE running Android 12 security patch May 1, 2022, when I go to install the ATAK-forwarder plugin from within ATAK it successfully installs, but the ATAK never acknowledges the installation.

Comparing the installation against a phone where it does work
ApkUpdateReceiver never receives the onReceive: android.intent.action.PACKAGE_ADDED

Note, I have installed other plugins such as WASP, and the package added has been received. I've uninstalled and reinstalled forwarder, have used previous versions of forwarder, attempted older versions of ATAK along with aligned older versions of forwarder, all with no luck.

Attached is a clean start and attempted install. It's hard to show the missing log entry, but I'm sure you know better than myself what to look for.
logcat6.txt

ITAK

Are you thinking of making a version for an iTAK-Forwarder?
I'm trying to set up an entirely IOS dependant system and was pleased to see TAK made an IOS version.
If not is there a way to make this work for that application.

RFE: show some flexibility about ATAK version

For complex reasons, I am stuck to using ATAK 4.3 currently, and when compiling version 1.0.1 of the plugin I had my first encounter with (closed) issue #86 - specifically the plugin compiled OK against the 4.3.0 tree without any complaints, but when trying to actually load it into ATAK 4.3.0, it got rejected as an incompatible version as apparently the plugin required version 4.4.0.

Long story short, I traced the issue to this line:

ext.ATAK_VERSION = "4.4.0"

To fix the problem, I added the following 3 lines just below:

    def ENV_ATAK_VERSION = System.getenv('ATAK_VERSION')
    if (ENV_ATAK_VERSION)
        ext.ATAK_VERSION = ENV_ATAK_VERSION

And compiled the plugin with:
ATAK_VERSION="4.3.0" ./gradlew assembleCivDebug

This solved the problem for me, but since the solution is a bit dirty and unscientific, I am reluctant to open a PR. Up to you, Paul, whether to include it in the official build.gradle or just as a note in the README.

Forwarder plugin not installed.

Hey all. Apologies in advance, as I am new to this and have been scratching my head for a week or so on this issue. With two android devices, I can't seem to actually install the forwarder plugin into ATAK.
-latest Forwarder apk from binaries
-latest atak apk
-manually placed forwarder apk into "Custom" folder before installing
-ATAK has full permissions

Screenshot_20220429-120831_ATAK

NullPointerException on MeshDeviceConfigurator.onConnectionStateChanged.

java.lang.NullPointerException

java.lang.NullPointerException:
at com.paulmandal.atak.forwarder.comm.meshtastic.MeshDeviceConfigurer.checkOwner (SourceFile:5)
at com.paulmandal.atak.forwarder.comm.meshtastic.MeshDeviceConfigurer.onConnectionStateChanged (SourceFile:7)
at com.paulmandal.atak.forwarder.comm.meshtastic.MeshServiceController.a (SourceFile:1)
at com.paulmandal.atak.forwarder.comm.meshtastic.MeshServiceController.b (Unknown Source)
at com.paulmandal.atak.forwarder.comm.meshtastic.h.run (Unknown Source:4)
at android.os.Handler.handleCallback (Handler.java:938)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:223)
at android.app.ActivityThread.main (ActivityThread.java:7656)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:947)

After PR #90, tracker callsigns aren't shown on the map anymore

Hi Paul, welcome back! :)

Excellent work on the last updates, I love the way the inactive trackers fade off the map, but there's a small regression.
The trackers shown on the map of the EUD are shown with generic names "Tracker-XXXXXXXX" instead of the Meshtastic owner name field.

I think this is due to the drawTracker() function receiving data derived directly from the POSITION messages (which don't include a name) instead of the stored TrackerUserInfo record (which includes both name and position data).

I will raise a PR for your consideration, with the change that fixed this for me.

Binary APK releases

I am a TAK and Meshtastic user (and occasional bug reporter) and would really like to test this plugin, however I don't have a full ATAK build environment and no resources to set one up right now.

For me and other people in my situation, it would be really nice if your project could publish binary releases of the plugin, along with the unofficial ATAK APK patched with your signing key. I believe it would remove a significant barrier to adoption.

Thank you.

Stale Meshtastic nodes not filtered out

The Meshtastic devices keep a persistent list of known nodes, for many days after a node was last seen (even across node reboots - I don't actually know an easy way to take a node off that list).
The firmware does, however, provide a lastSeen timestamp in the NodeInfo object to enable a user to determine a nodeโ€™s freshness and handle it accordingly.

Currently the atak-forwarder plugin appears to pick up this known nodes list on a wholesale basis and without accounting for freshness. As a result, nodes that have been stale for several days can be displayed side-by-side with online nodes, with no ability to discriminate between these cases, causing information pollution.

Suggestion

Define a freshness limit in software (somewhere between 10-30 minutes) and filter out stale nodes on this basis.

ATAK Forwarder shows up as available, but wont install

Screenshot_20220705-141606_ATAK
Screenshot_20220705-141617_ATAK

The APK forwarder shows up as an available plug-in, I install it, and it runs through the process, but never installs. I have tried it with an older version and a newer version of ATAK. I have the uptodate forwarder. Phone is a Samsung s20 ultra. I don't think I've missed anything. I've downloaded both, placed the forwarder in the customs/apk folder, but it doesn't work. If anyone knows what the cause is, I would super appreciate it.

Incompatible altitude values from standalone meshtastic devices

The CoT schema specifies that altitude must use the HAE (height above ellipsoid) model, and strongly discourages the use of the alternative MSL (mean sea level) model.

MSL is empirically derived (as is AGL from DTED). MSL is based on an estimate of โ€œsea levelโ€
which is affected by the density of the Earthโ€™s crust. โ€œSea levelโ€ is actually an irregular,
undulating surface thatโ€™s higher where the crust is densest. The shape of this surface is modeled
by a big 2-D table of measurement, an Earth Gravity Model (EGM). The model is refined
periodically [...]
In short, MSL is an interoperability nightmare. You have to have the same model, gridding, and
interpolation to exchange information, or errors will result. All this is avoided if we use HAE.
HAE is a mathematical model with just a few parameters for ellipse axes. Itโ€™s simple, accurate,
and stable.
(Mike Butler, 2005, The Developerโ€™s Guide to Cursor on Target)

However, the meshtastic firmware is currently using the MSL model, which makes the altitude data from meshtastic devices effectively unusable for CoT purposes.

I have raised the issue with the meshtastic project: meshtastic/firmware#359

RFE: double encrypt all Meshtastic messages

In some cases, one or more ATAK user groups may need to communicate over a shared, or even public Meshtastic channel - for example, when using pre-existing network infrastructure to increase coverage. In these cases, the Meshtastic built-in channel encryption layer is insufficient to ensure the secrecy and integrity of the communications.

For these cases, it would be really useful to have a second in-app encryption layer controlled from the plugin settings - which encrypts all messages prior to sending to the Meshtastic channel using a separate pre-shared key that never leaves the EUD.
Similar to the ATAK builtin function AES-256 Mesh Encryption, but for Meshtastic comms.

It would be really useful even in case of loss of a Meshtastic radio, which is currently a fatal attack vector as each radio contains the channel key in cleartext.

Small inaccuracies in non-TAK CoT events for standalone devices

A few small inaccuracies in the generated CoT events from standalone meshtastic devices

1) meshtastic-device locations are always gps-generated

Currently the event "how" attribute is hard-coded to h-e ("human-estimated").


In reality, the location data from meshtastic devices is either sourced from a GPS receiver, when available, or not included at all. The "how" attribute can be safely hard-coded to m-g ("machine-generated by GPS receiver")

Additionally, the geopoint source is hard-coded to USER; it should probably be GPS

precisionLocationDetail.setAttribute(TAG_GEOPOINTSRC, VALUE_USER);

2) altitude source should be GPS not DTED (but not yet)

Currently the "precision altsrc" attribute is hard-coded to DTED0, but the code simply passes through the altitude from the meshtastic device, which is GPS-derived. In the ideal case, the altsrc should be GPS.
However since the altitude value provided by meshtastic is not CoT compatible (issue #36), in the short term the best value is probably "???"

See: https://github.com/deptofdefense/AndroidTacticalAssaultKit-CIV/blob/master/atak/MapCoreInterfaces/lib/src/main/java/com/atakmap/coremap/maps/coords/GeoPointMetaData.java

3) default role "RTO" is not the typical role of standalone meshtastic devices

I suggest "Team Member" as a neutral, safe default.

4) UIDs not sufficiently collision-proof

In general, CoT UIDs are supposed to uniquely identify individual real-world entities. For this, they need to be deterministic (same entity same UID) but also globally unique or, at least, reasonably collision-proof.
Currently the UID is set to the meshtastic device's longName, which is informational, user-specified and frequently reused across multiple devices. It is neither required nor strongly expected to be unique.

I suggest using a UID derived from the device's node ID, which in its turn is derived from the CPU's serial number or MAC address and is expected to be unique as a matter of network operation. For example: MESHTASTIC-1234abcd

Proposed simplification of CoT event dispatching

The change from PR #39 works as intended and fixes issue #35 (but not #34 since it only dispatches internally). However, since API methods are now used that provide appropriate abstraction, the additional layer of abstraction via mCotDispatcher seems to me somewhat redundant.

I suggest that rewriting the function retransmitCotToLocalhost() to invoke the dispatcher methods directly could reduce some of the complexity without impacting the code structure - and fix issue #34 in one fell swoop.

Here's what worked well for me (in InboundMessageHandler.java ):

import com.atakmap.android.cot.CotMapComponent;
[...]

    public void retransmitCotToLocalhost(CotEvent cotEvent) {
        CotMapComponent.getInternalDispatcher().dispatch(cotEvent);
        CotMapComponent.getExternalDispatcher().dispatch(cotEvent);
    }

(the second line dispatches the CoT event externally, fixing issue #34)

I'm reluctant to submit a PR around this change since it should also include a cleanup of the InboundMessageHandler class - a task requiring a level of familiarity with your code that I don't have yet. :) But I hope it helps nonetheless.

"Comm device disconnected" and changes in ATAK are not implemented despite Meshtastic app is connected.

Hey Paul,
this is my first GitHub issue entry so please excuse possible mistakes.
Tbeam module is running fine and connects with mashtastic app, all options are available.
Module shows up in plugin settings and if channel name, mode/speed or PSK is changed in ATAK the device restarts but changes are not implemented.
The @ stays red and the message mentioned above shows up every ATAK start.
I found a similar case in the closed issues with the remark that the version was not supported, same case here?
Thanks in advance.

Meshtastic firmware version: 1.2.59.d81c1c0
Meshtastic app version: 1.2.61
ATAK version: v4.6.0.4 (72eb2c83) [playstore]
Plugin version: 1.0.6-1-4.6.0
Samsung S9 Android version: 10

Signing the plugin

Not really an issue with this app, but just having trouble figuring out how/what key to add to the AtakPluginRegistry.ACCEPTABLE_KEY_LIST when building a release version of ATAK. I tried the public key from the generated keystore that I would be using for atak-forwarder, and followed the directions from the README provided in the atak-civ plugin signing instructions, which instruct to sign with RSA and SHA1withRSA. With all of that still no luck, atak does not recognize the key. I was hoping you had successfully built a release version of atak and your atak-forwarder app, and could share some how-to steps on achieving this.
Thanks!

Usability: Poor UI rendering on WVGA / FWVGA devices

On devices with screen resolutions between 480x800 - 480x900 the plugin's UI rendering is distorted, bordering on unusable, even though the rest of ATAKโ€™s UI renders flawlessly even at 480x800.

There are a few issues:

  • Word-splitting in tab labels causing a multi-line effect, further reducing the usable screen area
  • "Target device" label overlaps comm device fields above
  • Comm device ID is overlapped by Comm toggle switch (use of a toggle switch type control is really not optimal in this context as it uses twice the width it really needs)
  • "Set Comm Device" overlaps "Refresh" on WVGA screens
  • also, on one WVGA device (not shown), the Comm Device line actually word-wraps

Screenshot_00

  • packet counters line gets "pushed" to the left outside visible area - increasingly so as the numbers grow in size
  • the "Dlvd" label word-wraps

Screenshot_01

  • more button overlap, here "Clear Data" overlaps "Clear MsgQ" completely

Screenshot_02

Meshtastic 1.3

Hey Paul!

Just a heads up.... Meshtastic 1.3 is being worked on which includes a lot of major changes, including a rewrite of how we use bluetooth. Part of this is a rework of the protos.

Please be aware that when 1.3 comes out in beta, it's very likely you'll have compatibility issues and may need to have some version detection.

1.3 has no plans for backward compatibility with 1.2.

When 1.3 goes live and out of beta, it will be called 2.0.

Cheers!

Feature Request

From the Readme:
Automatically adjust link speed / range based on # of lost messages
Use T-Beam as a GPS source (if it proves to be more accurate than the phone's)
Message IDs and receipt confirmation
Improve chat message shrinking further
Smarter sending -- Map Markers get higher priority unless PLI has not gotten sent in ~5 minutes
Smarter sending -- Send a list of map markers to group, other clients can reply with which marker they are missing, build up a list of missing markers if more than 1 person is missing send to group, otherwise send to individuals
Needs more real-world stability testing
Re-add GoTenna support with a proper abstraction for communication layer

Some additional from me.
Find my T-Beam: Have keep-alive sent to local T-beam. If keep-alive is lost, T-Beam will broadcast it's location at a preset interval and set a marker where it was when it was lost and where it last successfully got a keep-alive.

Message queuing and prioritization: Might just be what you have above, include things like rate limits etc.

PLI rounding: If last PLI was within a certain distance discard it unless it's been a preset time.

Tracker: absent units keep being advertised eternally

After a tracker leaves the network and becomes stale, the Forwarder plugin keeps broadcasting that tracker's PLI at the last location, using stale CoT packets based on the time of last activity.

Example:

09-01 23:32:03.998 31437 31698 V FWDDBG.TrackerCotGenerator: drawTracker() callsign: K************, meshId: !99999999, atakUid: null
09-01 23:32:03.999 31437 31698 V FWDDBG.TrackerCotGenerator:   Tracker last seen: 8817144ms ago vs. trackerStaleTime: 300000, drawing stale: true

As far as I can tell, this stale point broadcast is repeated infinitely.

Why this is a problem

  1. creates visual clutter that is neither informative nor actionable
  2. creates unneeded network traffic
  3. gives the team incorrect information due to detail panel still showing the item as "Last report: 0m XXs ago" (time when last CoT packet was received) even though the actual icon is greyed out
  4. the tracker icon can't be deleted from screen - it comes back on every drawTracker() cycle
  5. the only way (that I know) to get rid of the stale icon is to restart ATAK

Suggestion: do not publish CoTs for stale trackers - just set the stale timestamp correctly based on the user preference, and let ATAK fade them organically.

Serial connection

Is it possible to make pli and chat exchange via bluetooth serial port without using meshtastic, only serial exchange?

โ€œSet Comm Deviceโ€ no effect until ATAK restart?

After upgrading to the ui-for-smaller-screens branch, my Comm Device setting was lost, as indicated by the orange @ symbol. I set it again in the Devices tab, however that had no effect on the connection status, and the symbol remained orange. Repeating the โ€œSet Comm Deviceโ€ operation a few times made no difference.

The only way to get the connection to activate was to restart ATAK, which caused the device to be finally recognized and the symbol to turn green.

I was unable to reproduce the bug and was almost going to dismiss it a one-off glitch, but later it happened identically on two other phones, so it may be worth looking into.

CoT events from Meshtastic aren't relayed back to TAK network

The expected behaviour with external comms plugins is that the events received via the plugin are relayed by the receiving EUD to the rest of the team through all connected interfaces (tagged to avoid loopback issues), to enable communication diversity without network splits.

Currently, inbound Meshtastic events are processed internally but not relayed via WiFi, VPN, IP multicast, TAK server etc. I suggest that they should also be relayed externally.

ATAK crash due to NullPointerException on receiving message

The plugin is working fine on most devices I've tried it on, except on two older phones (a Samsung S6 and a no-name MT6737), where it crashes ATAK with a NullPointerException. The backtrace is:

05-15 09:59:04.571 32249 32249 E ACRA    : ACRA caught a NullPointerException for com.atakmap.app.civ
05-15 09:59:04.571 32249 32249 E ACRA    : java.lang.NullPointerException: Attempt to read from field 'boolean androidx.lifecycle.LiveData$ObserverWrapper.mActive' on a null object reference
05-15 09:59:04.571 32249 32249 E ACRA    :      at androidx.lifecycle.LiveData.considerNotify(LiveData.java:117)
05-15 09:59:04.571 32249 32249 E ACRA    :      at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:146)
05-15 09:59:04.571 32249 32249 E ACRA    :      at com.paulmandal.atak.forwarder.plugin.ui.viewmodels.StatusViewModel.onMessageAckNack(StatusViewModel.java:141)
05-15 09:59:04.571 32249 32249 E ACRA    :      at com.paulmandal.atak.forwarder.comm.meshtastic.MeshSender.lambda$handleMessageStatusChange$3$MeshSender(MeshSender.java:339)
05-15 09:59:04.571 32249 32249 E ACRA    :      at com.paulmandal.atak.forwarder.comm.meshtastic.-$$Lambda$MeshSender$rt(...)Y.run(lambda)
05-15 09:59:04.571 32249 32249 E ACRA    :      at android.os.Handler.handleCallback(Handler.java:739)
05-15 09:59:04.571 32249 32249 E ACRA    :      at android.os.Handler.dispatchMessage(Handler.java:95)
05-15 09:59:04.571 32249 32249 E ACRA    :      at android.os.Looper.loop(Looper.java:158)

The software configuration is:

  • Android 6.0.0 (Mediatek) and 6.0.1 (Samsung) (factory install)
  • Google Play Services 20.06.16 (installed as an update)
  • Meshtastic app 1.2.31 (from github releases)
  • ATAK-4.3.0.0-03e312ec-civ-debug.apk (from Drive)
  • ATAK-Plugin-ATAK Forwarder-1.0.0-df0f358b-4.3.0-civ-debug.apk (from Drive)
  • devices: firmware-tbeam-1.2.30.80e4bc6.bin (from github releases)

Both affected phones are older models running Android 6, and none of the newer phones seem to be affected by this problem.

Cannot send messages via ATAK

Hi Paul. I'm having this issue where i have 2 t-beam devices connected to 2 phones and i'm trying to make these phones send and receive messages via ATAK. However, when i tried to send messages via ATAK, it didnt work, or very very slow (messages were received minutes after being sent). At the same time, when i send messages via Meshtastic app, it worked perfectly. The same thing happened with other ATAK packages as well. After a while, ATAK display that the other device was disconnected.
Here are my settings:

  • T-beam Firmware: 1.2.64
  • ATAK version: 4.4.0
  • ATAK Forwarder version: 1.1.1-4.4.0

protobuf RFE: floating point considered harmful :)

Floating point fields (and especially double-precision floats) are large, difficult to compress and overhead-y in both layout and operation.

In bandwidth-constrained contexts, like the atak-forwarder protobuf messages where every byte counts, a significant size reduction can be achieved by using exclusively integer fields.

Example

A latitude or longitude value (currently represented as a 64-bit double) can be instead represented using a 32-bit sfixed32 integer field with a 7-decimal precision (sufficiently accurate to "point to Waldo on a page" *) - and achieve an 8-byte saving per lat/lon point.

Proposal

Banish all floating-point fields from the protobuf definition, now and forever, and replace them with conservatively-sized integer fields.
Where possible, the integer values should be used verbatim. However, if the range of the chosen format does not fit the range of the variable comfortably, scaling and linear range mapping rules can be used to force a better range coverage.

*source: https://xkcd.com/2170/

Mesh packet type inconsistent with content

The plugin sends binary data objects over the meshtastic network, however the packet header falsely indicates the content type as CLEAR_TEXT (printable text) as a matter of default setting. This causes parsing errors in the firmware, as well as the python API.

It starts here:

And gets tagged with the default setting here (meshtastic codebase):
https://github.com/meshtastic/Meshtastic-Android/blob/312cf92b049a44f7bca891e67d9a72e619ef750d/app/src/main/java/com/geeksville/mesh/DataPacket.kt#L37

I believe (UNTESTED!) that the line above should say:
(...) new DataPacket(targetId, message, MeshProtos.Data.Type.OPAQUE_VALUE)

This should ensure that the packet is passed through with minimum friction and without giving the meshtastic network any headaches.

Suggestion: do not name the radio with the owner's callsign

Currently, the plugin sets (and stubbornly re-sets) the radio name to the ATAK callsign. I think the code responsible for this is around here:

public UserInfo(String callsign, String meshId, @Nullable String atakUid, @Nullable Integer batteryPercentage) {
this.callsign = callsign;

This is not the best approach, for two reasons:

  1. when the radio is peered to the EUD, its name is irrelevant from an ATAK perspective - the callsign of the unit is set in the CoT packets
  2. however, when the radio and the ATAK EUD become separated and the radio starts beaconing stand-alone, the EUD and the radio will plot on the map as two separate units with the same callsign, which is not ideal

I suggest, instead of setting the radio name to the unit callsign, to set it to a variation of the callsign, indicating that it is a related, but distinct unit.

For example, if the ATAK callsign is ALICE and the radio's 16-bit node ID is 0xc4f3, set the radio name to ALICE-MX-c4f3.

This will ensure that the radio's ownership information is retained (to aid in a recovery operation), while preventing the radio from accidentally impersonating its owner in the process. The numeric suffix enables even multiple lost units to be individually identified.

mobilinkd support!

Hey Paul, been following the project closely - super relevant to my interests and I'm really excited someone else is hacking on the same stuff I am. You've tackled a lot of the stuff I have on my feature wishlist, too.

I've got a mobilinkd TNC and would love to use it to send PLI's - right now I'm using a delightfully Rube Goldberg setup involving direwolf and netcat.

It's been a long time since I've written any Java in anger, but I'll aim to get an environment up this coming weekend. I'll probably run into questions along the way, is there a better place to throw questions your way other than here?

My first one is about what the development lifecycle looks like - is there a way to disable plugin signature checking on a build of ATAK so I can iterate, or do you have another way for iterating on plugin code? I can stub & test a bit, but I'm sure there will be a bit of testing in prod.

ATAK Forwarder not populating in Tool Preferences

ATAK version 4.4.0.8
Plug-in API version 4.4.0.MIL
Meshtastic app version 1.2.45
Meshtastic firmware version 1.2.48
ATAK Forwarder version 1.0.3-1-4.4.0-civ-release.apk
Android version 8.0.0

The Meshtastic app and device are working fine on their own. ATAK Forwarder is successfully installed and loaded into ATAK, but there is no way to actually interact with the plugin within ATAK. It does not show anywhere besides the TAK Package Management screen.

Additionally, if I send a message through the Meshtastic app, it crashes ATAK on the sending device.

PXL_20211215_222637708 MP
PXL_20211215_222653770 MP
PXL_20211215_222715694

Error in message handling - "ack/nack" errors

Android Version: Tested on 10 & 12.1
Firmware Version: 1.2.52
Meshtastic App Version: 1.2.52 (also tested on 1.2.51/1.2.53/1.2.55/1.2.61)
ATAK Version: 4.6.0.3
ATAK Forwarder Version: 1.0.6

I have noticed an issue regarding, what I believe to be, the connection between ATAK and the Meshtastic app.

I connect to the radio via bluetooth and can send/receive messages over the air via the Meshtastic app. I can also get ATAK to show "connected" and start to send broadcast signals, however, these signals immediately fail and are counted as errors. I checked the debug panel in the Meshtastic app and did not see any packets tx/rx from "atak forwarder".

I checked logcat during ATAK startup and received the following.

04-13 00:02:12.220 11857 11857 D FWDDBG.i4: Mesh connected: true
04-13 00:02:12.223 11857 11857 V FWDDBG.i4: Notifying connection state listener: 39588367, state: DEVICE_CONNECTED
04-13 00:02:12.224 11857 11857 V FWDDBG.i4: Notifying connection state listener: 11726970, state: DEVICE_CONNECTED
04-13 00:02:12.224 11857 11857 V FWDDBG.i4: Notifying connection state listener: 164741163, state: DEVICE_CONNECTED
04-13 00:02:12.224 11857 11857 V FWDDBG.i4: Notifying connection state listener: 57650187, state: DEVICE_CONNECTED
04-13 00:02:12.224 11857 11857 V FWDDBG.i4: Notifying connection state listener: 230404603, state: DEVICE_CONNECTED
04-13 00:02:12.224 11857 11857 V FWDDBG.i4: Notifying connection state listener: 104, state: DEVICE_CONNECTED
04-13 00:02:12.227 11857 11857 V FWDDBG.P3: onUserDiscoveryBroadcastReceived, callsign: xxxx, meshId: xxxx, atakUid: ANDROID-xxxx
04-13 00:02:12.227 11857 11857 V FWDDBG.P3: Adding new user from discovery broadcast: xxxx, atakUid: ANDROID-xxx
04-13 00:02:12.229 11857 11857 V FWDDBG.e4: Checking owner
04-13 00:02:12.230 11857 11857 V FWDDBG.e4: Setting radio owner longName: xxxx, shortName: x
04-13 00:02:12.231 11857 11857 V FWDDBG.e4: Checking radio config
04-13 00:02:12.266 11857 11857 V FWDDBG.e4: Checking channel config for channel: xxxx, mode: 4, psk: xxxx
04-13 00:02:12.280 11857 11857 V FWDDBG.e4: target channel: xxxx, found! checking PSK and modemConfig
04-13 00:02:12.280 11857 11857 V FWDDBG.e4: channel: , found, not target
04-13 00:02:12.280 11857 11857 V FWDDBG.e4: channel: xxxx, found, not target
04-13 00:02:12.281 11857 11857 V FWDDBG.e4: channel: , found, not target
04-13 00:02:12.281 11857 11857 V FWDDBG.e4: channel: , found, not target
04-13 00:02:12.281 11857 11857 V FWDDBG.e4: needsUpdate: false
04-13 00:02:12.362 11857 12183 I FWDDBG.g4: sendMessageInternal(), message length: 52 chunks: 1
04-13 00:02:12.362 11857 12183 D FWDDBG.g4: sendNextChunk()
04-13 00:02:12.362 11857 12183 D FWDDBG.g4: sendChunk()
04-13 00:02:12.374 11857 12183 I FWDDBG.g4: ---> Sent packet: ATAKBCAST,meshid,ANDROID-xxxx,callsign,1
04-13 00:02:12.374 11857 12183 I FWDDBG.g4: messageChunk: 1/1 to: ^all, waiting for ack/nack id: -1181019467

shortly after I receive

04-13 00:02:27.027 11857 12418 I FWDDBG.g4: handleMessageStatusChange, got the message we ACK/NACK we're waiting for id: -1181019467, status: ERROR
04-13 00:02:27.028 11857 12418 I FWDDBG.g4: Status is ERROR, resending chunk after 5000ms

In short:
What works

  • Meshtastic text messages
  • ATAK forwarder successfully changes my radio's name, channel name, channel mode

What doesn't work

  • ATAK forwarder packets to meshtastic app

I believe the issue falls between the meshtastic app and the forwarder, as the meshtastic app successfully sends and receives text messages and the debug panel shows these packets, but fails to show any packets relating to ATAK forwarder.

Let me know if I can provide any more information or testing. I would be happy to help in any way I can.

Forwarder crashes ATAK immediately after installation

I am new to ATAK and to Git. I did look around and this seems like the right place to post this issue. If this is the wrong place please tell me where to post.

Phone is Samsung Galaxy S7, model SM-G930V. Android version 8.0.0.

Summary, ATAK crashes immediately after installing ATAK Forwarder.

  1. Uninstall ATAK play store addition.
  2. Delete ATAK folder.
  3. Download and Install ATAK from tak.gov.
  4. Copy file "ATAK-Plugin-ATAK.Forwarder-1.1.3-1-4.7.0-civ-release.apk" from Git to "This PC\Galaxy S7\Phone\atak\support\apks\custom"
  5. Open ATAK, click settings, Tool Preferences, Package management, click sync, click ATAK Forwarder, click Install.
  6. When installation finishes, ATAK crashes - log file attached - file extension changed from JSON to TXT.
  7. ATAKCRASH_2022_08_05_14_24_45.txt
  8. uninstall ATAK forwarder
  9. repeat step 5, crashed again at step 6 with same message in log.

I successfully installed Forwarder on a Samsung Galaxy tab A7. SM-T220, android version 11.

Tracker: stale locations presented as fresh in marginal coverage conditions

I think I've found an interesting edge case in the stand-alone tracker handling. I'll describe the user perspective first, then the technical side.

I have a Meshtastic tracker moving in and out of my coverage range, in such a way that its (re-)entry point (where I start receiving its messages) is completely different from its exit point (where it loses coverage).

In ATAK, I see the tracker icon moving away from me, then, once out of range, it freezes and starts fading. This is normal and expected behavior. However: when the tracker re-enters coverage hours later (at a different point as discussed), its icon first "comes back to life" at the old point of last contact instead of the tracker's actual location. If the coverage remains good, the icon eventually jumps to the correct location, and the tracking continues normally.

Technically, I suspect that this may be caused by the NODEINFO packets triggering a CoT update in the plugin. So, if a NODEINFO packet is the first one received after the break, the ensuing CoT update will contain the last recorded location values, per the last POSITION packet received before the break.

if (dataType == Portnums.PortNum.NODEINFO_APP.getNumber()) {
try {
MeshProtos.User meshUser = MeshProtos.User.parseFrom(payload.getBytes());
mLogger.v(TAG, "NODEINFO_APP parsed NodeInfo: " + meshUser.getId() + ", longName: " + meshUser.getLongName() + ", shortName: " + meshUser.getShortName());
TrackerUserInfo trackerUserInfo = new TrackerUserInfo(meshUser.getLongName(), meshUser.getId(), null, TrackerUserInfo.NO_LAT_LON_ALT_VALUE, TrackerUserInfo.NO_LAT_LON_ALT_VALUE, TrackerUserInfo.NO_LAT_LON_ALT_VALUE, false, meshUser.getShortName(), System.currentTimeMillis());
mTrackerListener.onTrackerUpdated(trackerUserInfo);
} catch (InvalidProtocolBufferException e) {

One possible complicating factor is that NODEINFO packets are physically smaller than POSITION packets, and as such, they have a smaller risk of corruption/loss in a marginal coverage situation. This means that, in the scenario above, a NODEINFO packet has a higher than 50% chance of being the first one received.

My suggestion (assuming that my analysis is correct) is to consider not triggering CoT updates on NODEINFO packets - either via a boolean argument to function onTrackerUpdated() or another way of discriminating between POSITION and NODEINFO updates.

Thank you.

Split plugin into ATAK/Meshtastic halves?

I'm not sure if the ATAK product center would allow this, but have you considered splitting the Meshtastic stuff into another APK that doesn't need to go through the signing process?

This would allow for development towards the MT half to proceed at a pace while simplifying the ATAK stuff enough that it might be possible to stay current on the signing process.

Also, thanks for this great project. Once everything stabilizes some both here and in Meshtastic I think this is going to become a premier use case for ATAK and MT.

Crash

Running atak 4.5.1.4 with the latest forwarder and atak instantly crashes when you click on Atak forwarder preferences. Running a pixel 5 with android 12

New "team color" field in Meshtastic NODEINFO

As of merged PR meshtastic/protobufs#33 , the Meshtastic User protobuf (used in NODEINFO messages) contains a new field named team which can be set to any of the 14 colors in the ATAK team color palette.

This can be used to persistently assign different team colors to standalone tracker devices, instead of a single color configured in the Forwarder plugin, as we do now.

Full support of the new field is still WIP; should become available in the next couple of weeks.

BUG: plugin overwrites the firmware region setting (NEW)

This one took a fair bit of debugging, but I think I found the problem.

Background

The meshtastic firmware has recently transitioned from separate region-specific builds (US/JP/EU/etc) to a one-build-fits-all model, with the region implemented as a configuration variable.

Currently

When running the ATAK plugin with meshtastic firmware 1.1.5+, and the region is set to a non-US value in the firmware, the region setting is being stubbornly reset by the plugin to the default (US) channel bandplan. This can place non-US users at risk.

Steps to reproduce

  • assuming tester is located in the US
  • use a tbeam board with firmware >= meshtastic/firmware@7ef2cc8
  • connect the tbeam board to a USB port
  • (on phone) pair the board with the Android app but DO NOT open ATAK yet
  • (on computer) using the python utility, change region to a non-US one in the 915MHz range (most of them are SUBSETS of the US range, so are safe to use in the US) - I use and recommend ANZ:
    meshtastic.py --debug --set region 6
  • (on computer) using a serial terminal, reboot the board via DTR pulse (Ctrl-A Ctrl-P in picocom) and watch the boot messages:
Loaded saved preferences version 11
Installing AES256 key!
legacy_region=1.0-EU, region=6, NODENUM=0xdeadbeef, dbsize=2
Wanted region 6, using ANZ
Starting meshradio init...
Set radio: name=ATAK, config=1, ch=6, power=0
Radio myRegion->freq: 916.000000
Radio myRegion->spacing: 0.500000
Radio myRegion->numChannels: 20

notice that the region setting is correctly honored

  • (on phone) start ATAK + forwarder plugin and connect to the board
  • (on computer) keep watching the messages in terminal until this line is encountered:
    Client is setting radio
  • (on computer) DTR-pulse the board again and watch the boot messages:
Loaded saved preferences version 11
Installing AES256 key!
legacy_region=1.0-EU, region=0, NODENUM=0xdeadbeef, dbsize=3
Wanted region 0, using Unset
Starting meshradio init...
Set radio: name=ATAK, config=1, ch=0, power=0
Radio myRegion->freq: 903.080017
Radio myRegion->spacing: 2.160000
Radio myRegion->numChannels: 13

Notice that, at this point, the board channel plan has been reset to US (default plan if unset, but illegal in most places!) and the incorrect setting even persists across reboots - until it is manually changed with the python tool.

Further information

The issue does not occur when changing the channel from the Meshtastic-Android app.

Request: Compatability with Motorola XPR IP stack

Howdy,

ATAK Forwarder already accomplishes so much with communicating with ATAK and with a Meshtastic device. One thing that I have not seen done is a Bluetooth SPP connection to a Motorola XPR radio with a built in IP stack. The later XPR radios have Bluetooth data sharing capabilities that allow for voice and data to be sent across the radio. In my opinion, this shouldn't be too hard to integrate into ATAK forwarder.

This is kind of a tall ask, but this could potentially offer better solutions to consumers and SAR teams that already have Motorola XPR radios!

Supported meshtastic versions

The README.md mentions:

The plugin has been tested with these versions of the Meshtastic dependencies. If you run into issues try installing these versions of the Meshtastic software to resolve them.

Dependency Version
Meshtastic-Android 1.2.64
Meshtastic-device 1.2.64

but it also mentions:

Set Up Meshtastic
Flash your devices with the lastest Meshtastic Firmware (The plugin has been tested with 1.1.5 beta, if you have issues try that version)
Install the Meshtastic App from the Play Store.

So which is the appropriate stable version of the firmware, 1.2.64 or 1.1.5 beta or something else (since the Play Store version is always changing)?

And does this recommendation apply to all versions of atak-forwarder or is there a minimum version of the forwarder that works with meshtastic-device 1.2.64 or 1.1.5 beta?

Binary release still current?

Hi, is the plugin binary in Gdrive still current? I can't get it to work for the life of me.
Meshtastic firmware: 1.2.45
Meshtastic app: 1.2.31
ATAK: 4.4.0.2

It will connect and setup the channel, but nodes won't see each other. Both my test EUDs keep showing "x repeated errors..." ie. all received packets are in error. Even the Meshtastic app won't talk/see each other any more outside of ATAK, despite the channel setup seemingly correct. Meshtastic worked correctly prior to running the plugin on ATAK.

What am I missing?

Inbound message relay using sockets instead of API methods

Currently, the inbound message relay uses a UDP socket to feed the CoT messages into ATAK's listening port. This approach works well in the default configuration, but is not optimal and has obvious limitations.

try (DatagramSocket socket = new DatagramSocket(INBOUND_MESSAGE_SRC_PORT)) {

The ATAK API has built-in, protocol agnostic methods for dispatching CoT events directly. I noticed, in the ATAK source code, the following method being used for a similar purpose:

import com.atakmap.android.cot.CotMapComponent;
(...)
CotMapComponent.getInternalDispatcher().dispatch(event);

Also, for the purpose of issue #34, CotMapComponent.getExternalDispatcher().dispatch() looks promising.

See: https://github.com/deptofdefense/AndroidTacticalAssaultKit-CIV/blob/master/atak/ATAK/app/src/main/java/com/atakmap/comms/CotDispatcher.java

I'm sorry, I still don't have a working ATAK build environment so it's a bit of a shot in the dark.

Is the patched Meshtastic app still required?

I noticed I've been accidentally running the plugin with the mainline Meshtastic-Android app with no apparent issues.

Is the requirement from the README (under "Build + Install Meshtastic") still relevant, or have the changes been merged into the mainline code in the meanwhile?

Invalid coordinates in nonAtakUserInfoFromNodeInfo() treated as valid

In function nonAtakUserInfoFromNodeInfo(), if the extraction of lat/lon/alt data fails, the function returns a 0/0/0 triplet which is indistinguishable from a valid result (0/0/0 is a real place on Earth), and is indeed treated as valid elsewhere in the code.

Position position = nodeInfo.getValidPosition();
if (position != null) {
lat = position.getLatitude();
lon = position.getLongitude();
altitude = position.getAltitude();
}
return new NonAtakUserInfo(meshUser.getLongName(), meshUser.getId(), nodeInfo.getBatteryPctLevel(), lat, lon, altitude, meshUser.getShortName());

This causes the standalone devices that lose GPS lock to be plotted at 0/0/0 on the ATAK map, causing a false teleportation effect.

Suggestion

There are 2 options:

  • Lazy fix: NodeInfo messages that fail getValidPosition() should be dropped without further processing
  • Serious fix: NodeInfo messages that fail getValidPosition() should update the battery info if available, and be otherwise CoT-ed at the unit's last known valid position with how='h-g-i-g-o'

In any case, using 0/0/0 as default values or error codes should probably be avoided in this context.

Local Device Not Found

ATAK forwarder wont install. When I try to, it asks to update the forwarder and then kicks me out. I'm assuming it has to do with the "local device not installed" any suggestions would help
Screenshot_20220510-111558_ATAK

Not compatible with 4.4.0RC.

The play store version of ATAK CIV was recently updated to 4.4.0RC and that version reports atak-forwarder as incompatible. 4.3.1 worked fine.

protobuf suggestion - use event type default

If we consider that:

  • the type field is mandatory in CoT events
  • statistically, type=a-f-G-U-C represents nearly 2/3 (possibly even more)* of all forwardable event types

It should be possible to use the following convention:

  • when encoding XML to protobuf:
    • if the type field is empty or absent, drop the XML message as invalid CoT
    • if type=a-f-G-U-C, do not include a type field in the protobuf at all
    • otherwise, include the type field literally, the way it's done currently
  • when decoding protobuf to XML:
    • if type field is present in protobuf, transfer literally to XML
    • if type field is absent, set type=a-f-G-U-C in XML

Considering that the 'a-f-G-U-C` string is 9 bytes + 2 protobuf overhead, this will result in an 11-byte saving in more than 2/3 of the cases, with no negative impact on the other 1/3.

*source: personal research

Playstore reported Crash NullPointerException

Pull from the Playstore Reporting Metrics - unfortunately no steps for reproduction. (Reported within the last 7 days of the date of this filing)

Crash
Lenovo Tab M10 (FHD)
brightness_1
Android 9 (SDK 28)
brightness_1
1649938081.apk
brightness_1
113 minutes ago
Type

java.lang.NullPointerException

java.lang.NullPointerException:
at java.util.Objects.requireNonNull (Objects.java:203)
at com.geeksville.mesh.ChannelProtos$ChannelSettings.setModemConfig (SourceFile:1)
at com.geeksville.mesh.ChannelProtos$ChannelSettings.access$400 (SourceFile:1)
at com.geeksville.mesh.ChannelProtos$ChannelSettings$Builder.setModemConfig (SourceFile:2)
at atakplugin.PluginTemplate.e4.n (SourceFile:9)
at atakplugin.PluginTemplate.e4.k (SourceFile:17)
at atakplugin.PluginTemplate.e4.g (SourceFile:26)
at com.paulmandal.atak.forwarder.plugin.c.onSharedPreferenceChanged (SourceFile:4)
at android.app.SharedPreferencesImpl$EditorImpl.notifyListeners (SharedPreferencesImpl.java:607)
at android.app.SharedPreferencesImpl$EditorImpl.apply (SharedPreferencesImpl.java:489)
at android.preference.Preference.tryCommit (Preference.java:1590)
at android.preference.Preference.persistString (Preference.java:1626)
at android.preference.EditTextPreference.setText (EditTextPreference.java:94)
at android.preference.EditTextPreference.onDialogClosed (EditTextPreference.java:148)
at android.preference.DialogPreference.onDismiss (DialogPreference.java:395)
at android.app.Dialog$ListenersHandler.handleMessage (Dialog.java:1393)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:193)
at android.app.ActivityThread.main (ActivityThread.java:6758)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:858)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.