Skip to content

Commit

Permalink
1.0.18
Browse files Browse the repository at this point in the history
More tweaks on mesh nodes displayed in ATAK

Add preferences for reporting rates
  • Loading branch information
niccellular committed May 9, 2024
1 parent ad38bc6 commit 8a1020d
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 74 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
buildscript {


ext.PLUGIN_VERSION = "1.0.17"
ext.PLUGIN_VERSION = "1.0.18"
ext.ATAK_VERSION = "4.10.0"

def takdevVersion = '2.+'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
import android.content.IntentFilter;
import android.content.ServiceConnection;

import android.content.SharedPreferences;
import android.os.IBinder;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.widget.Toast;

import com.atakmap.android.maps.MapView;
import com.atakmap.android.maps.AbstractMapComponent;
import com.atakmap.android.meshtastic.plugin.R;
import com.atakmap.app.preferences.ToolsPreferenceFragment;
import com.atakmap.coremap.filesystem.FileSystemUtils;
import com.atakmap.coremap.log.Log;
import com.atakmap.coremap.cot.event.CotEvent;
import com.atakmap.coremap.cot.event.CotDetail;
Expand Down Expand Up @@ -46,38 +49,22 @@
import java.util.List;
import java.util.Locale;

import kotlin.reflect.jvm.internal.impl.load.kotlin.JvmType;

public class MeshtasticMapComponent extends AbstractMapComponent implements CommsMapComponent.PreSendProcessor {

public class MeshtasticMapComponent extends AbstractMapComponent implements CommsMapComponent.PreSendProcessor, SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "MeshtasticMapComponent";

private Context pluginContext;
public static CotShrinkerFactory cotShrinkerFactory = new CotShrinkerFactory();
public static CotShrinker cotShrinker = cotShrinkerFactory.createCotShrinker();

public enum ServiceConnectionState {
DISCONNECTED,
CONNECTED
}

private static IMeshService mMeshService;
private static ServiceConnection mServiceConnection;

private static Intent mServiceIntent;

public static ServiceConnectionState mConnectionState = ServiceConnectionState.DISCONNECTED;


/**
* Service Intent
*/
public static final String PACKAGE_NAME = "com.geeksville.mesh";
public static final String CLASS_NAME = "com.geeksville.mesh.service.MeshService";

/**
* Intents the Meshtastic service can send
*/
public static final String ACTION_MESH_CONNECTED = "com.geeksville.mesh.MESH_CONNECTED";
public static final String ACTION_MESH_DISCONNECTED = "com.geeksville.mesh.MESH_DISCONNECTED";
public static final String ACTION_RECEIVED_ATAK_FORWARDER = "com.geeksville.mesh.RECEIVED.ATAK_FORWARDER";
Expand All @@ -87,10 +74,6 @@ public enum ServiceConnectionState {
public static final String ACTION_TEXT_MESSAGE_APP = "com.geeksville.mesh.RECEIVED.TEXT_MESSAGE_APP";
public static final String ACTION_NODE_CHANGE = "com.geeksville.mesh.NODE_CHANGE";
public static final String ACTION_MESSAGE_STATUS = "com.geeksville.mesh.MESSAGE_STATUS";

/**
* Extra data fields from the Meshtastic service
*/
public static final String EXTRA_CONNECTED = "com.geeksville.mesh.Connected";
public static final String EXTRA_DISCONNECTED = "com.geeksville.mesh.disconnected";
public static final String EXTRA_PERMANENT = "com.geeksville.mesh.Permanent";
Expand All @@ -104,6 +87,8 @@ public enum ServiceConnectionState {
public static final String ACTION_CONFIG_RATE = "com.atakmap.android.meshtastic.CONFIG";
public static MeshtasticWidget mw;
private MeshtasticReceiver mr;
private SharedPreferences prefs;

public static List<byte[]> divideArray(byte[] source, int chunksize) {

List<byte[]> result = new ArrayList<>();
Expand Down Expand Up @@ -138,7 +123,6 @@ public static String getMyNodeID() {
return "";
}
}

@Override
public void processCotEvent(CotEvent cotEvent, String[] strings) {

Expand Down Expand Up @@ -239,6 +223,7 @@ else if (xpp.getAttributeName(i).equalsIgnoreCase("speed"))
}
} catch (XmlPullParserException | IOException e) {
e.printStackTrace();
return;
}

ATAKProtos.Contact.Builder contact = ATAKProtos.Contact.newBuilder();
Expand Down Expand Up @@ -434,7 +419,7 @@ else if (xpp.getAttributeName(i).equalsIgnoreCase("speed"))
try {
mMeshService.send(dp);
} catch (RemoteException e) {
throw new RuntimeException(e);
e.printStackTrace();
}
return;
}
Expand All @@ -454,13 +439,15 @@ else if (xpp.getAttributeName(i).equalsIgnoreCase("speed"))
System.arraycopy(c, 0, combined, chunk_hdr.length, c.length);
} catch (Exception e) {
e.printStackTrace();
return;
}
// send out 1 chunk
dp = new DataPacket(DataPacket.ID_BROADCAST, combined, Portnums.PortNum.ATAK_FORWARDER_VALUE, DataPacket.ID_LOCAL, System.currentTimeMillis(), 0, MessageStatus.UNKNOWN, 3, 0);
try {
mMeshService.send(dp);
} catch (RemoteException e) {
throw new RuntimeException(e);
e.printStackTrace();
return;
}
}

Expand All @@ -469,19 +456,20 @@ else if (xpp.getAttributeName(i).equalsIgnoreCase("speed"))
try {
mMeshService.send(dp);
} catch (RemoteException e) {
throw new RuntimeException(e);
e.printStackTrace();
return;
}
}
}


public void onCreate(final Context context, Intent intent, MapView view) {

CommsMapComponent.getInstance().registerPreSendProcessor(this);

context.setTheme(R.style.ATAKPluginTheme);
pluginContext = context;

prefs = PreferenceManager.getDefaultSharedPreferences(view.getContext());
prefs.registerOnSharedPreferenceChangeListener(this);

mr = new MeshtasticReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_RECEIVED_ATAK_FORWARDER);
Expand Down Expand Up @@ -533,21 +521,31 @@ public void onServiceDisconnected(ComponentName className) {
new PluginPreferencesFragment(
pluginContext)));
}


public static boolean reconnect() throws RemoteException {
boolean ret = getMapView().getContext().bindService(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
if (!ret) {
Toast.makeText(getMapView().getContext(), "Failed to bind to Meshtastic IMeshService", Toast.LENGTH_LONG).show();
}
return ret;
}


@Override
protected void onDestroyImpl(Context context, MapView view) {
view.getContext().unbindService(mServiceConnection);
view.getContext().unregisterReceiver(mr);
mw.destroy();
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key == null) return;
if (FileSystemUtils.isEquals(key, "plugin_meshtastic_rate_value")) {
String rate = prefs.getString("plugin_meshtastic_rate_value", "0");
Log.d(TAG, "Rate: " + rate);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("locationReportingStrategy", "Constant");
editor.putString("constantReportingRateUnreliable", rate);
editor.putString("constantReportingRateReliable", rate);
editor.apply();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.atakmap.android.meshtastic;

import static java.util.Objects.*;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
Expand All @@ -11,14 +9,11 @@
import android.preference.PreferenceManager;

import com.atakmap.android.cot.CotMapComponent;
import com.atakmap.android.editableShapes.EditablePolyline;
import com.atakmap.android.ipc.AtakBroadcast;
import com.atakmap.android.maps.MapView;
import com.atakmap.coremap.cot.event.CotDetail;
import com.atakmap.coremap.cot.event.CotEvent;
import com.atakmap.coremap.cot.event.CotPoint;
import com.atakmap.coremap.log.Log;
import com.atakmap.coremap.maps.coords.GeoPoint;
import com.atakmap.coremap.maps.time.CoordinatedTime;

import com.geeksville.mesh.ATAKProtos;
Expand All @@ -33,37 +28,15 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.UUID;

public class MeshtasticReceiver extends BroadcastReceiver {

private final String TAG = "MeshtasticReceiver";

private SharedPreferences prefs;
private boolean setRate = false;

@Override
public void onReceive(Context context, Intent intent) {

prefs = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
if (!setRate) {
SharedPreferences.Editor editor = prefs.edit();
editor.putString("locationReportingStrategy", "Constant");
editor.putString("constantReportingRateUnreliable", "120");
editor.putString("constantReportingRateReliable", "120");
editor.apply();
// } else if (message.equals("CONFIG_RATE_DYN")) {
// SharedPreferences.Editor editor = prefs.edit();
//editor.putString("locationReportingStrategy", "Dynamic");
editor.putString("dynamicReportingRateStationaryUnreliable", "120");
editor.putString("dynamicReportingRateMinUnreliable", "120");
editor.putString("dynamicReportingRateMaxUnreliable", "120");
editor.putString("dynamicReportingRateStationaryReliable", "120");
editor.putString("dynamicReportingRateMinReliable", "120");
editor.putString("dynamicReportingRateMaxReliable", "120");
editor.apply();
setRate = true;
}
String action = intent.getAction();
if (action == null) return;
Log.d(TAG, "ACTION: " + action);
Expand Down Expand Up @@ -261,17 +234,27 @@ public void onReceive(Context context, Intent intent) {
case MeshtasticMapComponent.ACTION_NODE_CHANGE:
NodeInfo ni = intent.getParcelableExtra("com.geeksville.mesh.NodeInfo");
if (ni == null) return;
Log.d(TAG, ni.toString());
if (ni.getUser() == null) return;
if (ni.getPosition() == null) return;
if (ni.getPosition().getLatitude() == 0 && ni.getPosition().getLongitude() == 0) return;
Log.d(TAG, ni.toString());

List<NodeInfo> nodes = MeshtasticMapComponent.getNodes();
if (nodes == null) {
Log.d(TAG, "nodes was null");
} else {
for (NodeInfo nodeInfo : nodes) {
if (nodeInfo == null) continue;
Log.d(TAG, nodeInfo.toString());
}
}

/*
if (ni.getUser().getId().equals(MeshtasticMapComponent.getMyNodeID())) {

if (ni.getUser().getId().equals(MeshtasticMapComponent.getMyNodeID()) && prefs.getBoolean("plugin_meshtastic_self", false)) {
Log.d(TAG, "Ignoring self");
return;
}
*/

if (prefs.getBoolean("plugin_meshtastic_tracker", false)) {
String nodeName = ni.getUser().getLongName();
CotDetail groupDetail = new CotDetail("__group");
Expand Down Expand Up @@ -345,7 +328,7 @@ public void onReceive(Context context, Intent intent) {
cotEvent.setStart(time);
cotEvent.setStale(time.addMinutes(10));

cotEvent.setUID(ni.getUser().getId());
cotEvent.setUID(String.valueOf(teamColor[0].hashCode()));
CotPoint gp = new CotPoint(ni.getPosition().getLatitude(), ni.getPosition().getLongitude(), ni.getPosition().getAltitude(), CotPoint.UNKNOWN, CotPoint.UNKNOWN);
cotEvent.setPoint(gp);
cotEvent.setHow("m-g");
Expand All @@ -354,14 +337,28 @@ public void onReceive(Context context, Intent intent) {
CotDetail cotDetail = new CotDetail("detail");
cotEvent.setDetail(cotDetail);
cotDetail.addChild(groupDetail);
CotDetail remarksDetail = new CotDetail("remarks");
remarksDetail.setInnerText(ni.toString());
cotDetail.addChild(remarksDetail);

CotDetail batteryDetail = new CotDetail("status");
batteryDetail.setAttribute("battery", String.valueOf(ni.getDeviceMetrics().getBatteryLevel()));
cotDetail.addChild(batteryDetail);

CotDetail takvDetail = new CotDetail("takv");
takvDetail.setAttribute("platform", "Meshtastic Plugin");
takvDetail.setAttribute("version", "1.0.18" + "\n----NodeInfo----\n" + ni.toString());
takvDetail.setAttribute("device", ni.getUser().getHwModelString());
takvDetail.setAttribute("os", "Meshtastic Plugin");
cotDetail.addChild(takvDetail);

CotDetail uidDetail = new CotDetail("uid");
uidDetail.setAttribute("Droid", teamColor[0]);
cotDetail.addChild(uidDetail);

CotDetail contactDetail = new CotDetail("contact");
contactDetail.setAttribute("callsign", teamColor[0]);
contactDetail.setAttribute("endpoint", "0.0.0.0:4242:tcp");
contactDetail.setAttribute("endpoint", "*:-1:tcp");
cotDetail.addChild(contactDetail);


new Thread(() -> {
if (cotEvent.isValid()) {
CotMapComponent.getInternalDispatcher().dispatch(cotEvent);
Expand All @@ -375,7 +372,6 @@ public void onReceive(Context context, Intent intent) {
break;
}
}

List<byte[]> chunks = new ArrayList<>();
boolean chunking = false;
int cotSize = 0;
Expand All @@ -387,6 +383,7 @@ protected void receive(Intent intent) {

if (dataType == Portnums.PortNum.ATAK_FORWARDER_VALUE) {
String message = new String(payload.getBytes());
/*
if (message.equals("CONFIG_RATE_CONSTANT")) {
SharedPreferences.Editor editor = prefs.edit();
editor.putString("locationReportingStrategy", "Constant");
Expand All @@ -403,7 +400,9 @@ protected void receive(Intent intent) {
editor.putString("dynamicReportingRateMinReliable", "120");
editor.putString("dynamicReportingRateMaxReliable", "120");
editor.apply();
} else if (message.startsWith("CHUNK")) {
} else
*/
if (message.startsWith("CHUNK")) {
Log.d(TAG, "Received Chunked message");
chunking = true;
if (cotSize == 0) {
Expand Down
17 changes: 17 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="rates">
<item>1 minute</item>
<item>5 minutes</item>
<item>10 minutes</item>
<item>20 minutes</item>
<item>30 minutes</item>
</string-array>
<string-array name="rate_values">
<item>60</item>
<item>300</item>
<item>600</item>
<item>1200</item>
<item>1800</item>
</string-array>
</resources>
Loading

0 comments on commit 8a1020d

Please sign in to comment.