Porównaj commity

...

3 Commity

Autor SHA1 Wiadomość Data
sh123 64e6b7f265 Add option to specify APRS-IS port 2023-11-12 16:42:08 +02:00
sh123 854bd629da Handle auto reply messages 2023-07-16 11:12:55 +03:00
sh123 1edf1c4c51 Message ack id parsing 2023-07-15 16:25:48 +03:00
13 zmienionych plików z 107 dodań i 18 usunięć

Wyświetl plik

@ -10,8 +10,8 @@ android {
applicationId "com.radio.codec2talkie"
minSdkVersion 23
targetSdkVersion 30
versionCode 162
versionName "1.62"
versionCode 164
versionName "1.64"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

Wyświetl plik

@ -299,7 +299,11 @@ public class AppWorker extends Thread {
String note = (textMessage.src == null ? "UNK" : textMessage.src) + "→" +
(textMessage.dst == null ? "UNK" : textMessage.dst);
sendStatusUpdate(AppMessage.EV_TEXT_MESSAGE_RECEIVED, note + ": " + textMessage.text);
_messageItemRepository.insertMessageItem(textMessage.toMessageItem(false));
if (textMessage.isAutoReply()) {
// TODO, acknowledge or reject message with the given (src, dst, ackId)
} else {
_messageItemRepository.insertMessageItem(textMessage.toMessageItem(false));
}
Log.i(TAG, "message received: " + textMessage.text);
}
@ -342,7 +346,9 @@ public class AppWorker extends Thread {
String note = (textMessage.src == null ? "UNK" : textMessage.src) + "→" +
(textMessage.dst == null ? "UNK" : textMessage.dst);
sendStatusUpdate(AppMessage.EV_TEXT_MESSAGE_TRANSMITTED, note);
_messageItemRepository.insertMessageItem(textMessage.toMessageItem(true));
if (!textMessage.isAutoReply()) {
_messageItemRepository.insertMessageItem(textMessage.toMessageItem(true));
}
}
@Override

Wyświetl plik

@ -61,6 +61,7 @@ public class AprsIs implements Protocol, Runnable {
private String _ssid;
private int _filterRadius;
private String _filter;
private int _defaultPort;
private final ByteBuffer _fromAprsIsQueue;
private final ByteBuffer _toAprsIsQueue;
@ -96,6 +97,7 @@ public class AprsIs implements Protocol, Runnable {
_filterRadius = Integer.parseInt(sharedPreferences.getString(PreferenceKeys.APRS_IS_RADIUS, "10"));
_filter = sharedPreferences.getString(PreferenceKeys.APRS_IS_FILTER, "");
_isLoopbackTransport = SettingsWrapper.isLoopbackTransport(sharedPreferences);
_defaultPort = Integer.parseInt(sharedPreferences.getString(PreferenceKeys.APRS_IS_TCPIP_SERVER_PORT, "14580"));
Log.i(TAG, "AprsIs RX gate: " + _isTxGateEnabled + ", TX gate: " + _isTxGateEnabled + ", server: " + _server);
@ -329,7 +331,7 @@ public class AprsIs implements Protocol, Runnable {
private TcpIp runConnect() {
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress(_server, APRSIS_DEFAULT_PORT));
socket.connect(new InetSocketAddress(_server, _defaultPort));
TcpIp tcpIp = new TcpIp(socket, "aprsis");
String loginCmd = getLoginCommand();
Log.i(TAG, "Login command " + loginCmd);

Wyświetl plik

@ -5,6 +5,7 @@ import com.radio.codec2talkie.protocol.position.Position;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -14,6 +15,7 @@ public class AprsDataTextMessage implements AprsData {
public String dstCallsign;
public String digipath;
public String textMessage;
public Integer ackId;
private boolean _isValid;
@ -37,6 +39,7 @@ public class AprsDataTextMessage implements AprsData {
this.dstCallsign = textMessage.dst;
this.textMessage = textMessage.text;
this.digipath = textMessage.digipath;
this.ackId = textMessage.ackId;
_isValid = true;
}
@ -52,6 +55,7 @@ public class AprsDataTextMessage implements AprsData {
textMessage.dst = this.dstCallsign;
textMessage.digipath = this.digipath;
textMessage.text = this.textMessage;
textMessage.ackId = this.ackId;
return textMessage;
}
@ -62,25 +66,56 @@ public class AprsDataTextMessage implements AprsData {
this.digipath = digipath;
this.srcCallsign = srcCallsign;
ByteBuffer buffer = ByteBuffer.wrap(infoData);
// callsign, trim ending spaces
byte[] callsign = new byte[9];
buffer.get(callsign);
this.dstCallsign = new String(callsign).replaceAll("\\s+$", "");
// ':' separator
byte b = buffer.get();
if (b != ':') return;
// message
byte[] message = new byte[buffer.remaining()];
buffer.get(message);
textMessage = new String(message, StandardCharsets.UTF_8);
// TODO, message id: {xxxxx (for auto ack)
String stringMessage = new String(message, StandardCharsets.UTF_8);
// ack/rej message
this.ackId = 0;
Pattern p = Pattern.compile("^(ack|rej)(\n+){1,5}$", Pattern.DOTALL);
Matcher m = p.matcher(stringMessage);
if (m.find()) {
String type = m.group(1);
if (type != null) {
String ackIdStr = m.group(2);
if (ackIdStr != null)
this.ackId = Integer.parseInt(ackIdStr);
}
} else {
// message requires acknowledge {xxxxx (for auto ack)
p = Pattern.compile("^(.+){0,67}[{](\\d+){1,5}$", Pattern.DOTALL);
m = p.matcher(stringMessage);
if (m.find()) {
this.textMessage = m.group(1);
String ackNumStr = m.group(2);
if (ackNumStr != null)
this.ackId = Integer.parseInt(ackNumStr);
} else if (stringMessage.length() <= 67) {
this.textMessage = stringMessage;
}
}
// TODO, telemetry, make subclass from message, extend and extract values
_isValid = !isTelemetry(textMessage);
if (this.textMessage != null)
_isValid = !isTelemetry(this.textMessage);
}
@Override
public byte[] toBinary() {
return String.format(":%-9s:%s", dstCallsign, textMessage).getBytes();
return (ackId > 0)
? String.format(Locale.US, ":%-9s:%s{%d", dstCallsign, textMessage, ackId).getBytes()
: String.format(":%-9s:%s", dstCallsign, textMessage).getBytes();
}
@Override

Wyświetl plik

@ -2,20 +2,41 @@ package com.radio.codec2talkie.protocol.message;
import com.radio.codec2talkie.storage.message.MessageItem;
import java.util.Locale;
public class TextMessage {
public String src;
public String dst;
public String digipath;
public String text;
public Integer ackId;
public MessageItem toMessageItem(boolean isTransmit) {
MessageItem messageItem = new MessageItem();
messageItem.setTimestampEpoch(System.currentTimeMillis());
messageItem.setNeedsAck(false); // TODO
messageItem.setIsTransmit(isTransmit);
messageItem.setSrcCallsign(this.src);
messageItem.setDstCallsign(this.dst);
messageItem.setMessage(this.text);
messageItem.setAckId(this.ackId);
messageItem.setIsAcknowledged(false);
messageItem.setRetryCnt(0);
return messageItem;
}
public boolean isAck() {
return this.text != null &&
this.text.toLowerCase(Locale.ROOT).equals("ack") &&
this.ackId > 0;
}
public boolean isRej() {
return this.text != null &&
this.text.toLowerCase(Locale.ROOT).equals("rej") &&
this.ackId > 0;
}
public boolean isAutoReply() {
return isAck() || isRej();
}
}

Wyświetl plik

@ -101,6 +101,7 @@ public final class PreferenceKeys {
public static String APRS_IS_ENABLE="aprs_is_enable";
public static String APRS_IS_CODE = "aprs_is_code";
public static String APRS_IS_TCPIP_SERVER = "aprs_is_tcpip_server";
public static String APRS_IS_TCPIP_SERVER_PORT = "aprs_is_tcpip_server_port";
public static String APRS_IS_ENABLE_RX_GATE = "aprs_is_enable_rx_gate";
public static String APRS_IS_ENABLE_TX_GATE = "aprs_is_enable_tx_gate";
public static String APRS_IS_ENABLE_SELF = "aprs_is_enable_self";

Wyświetl plik

@ -38,7 +38,8 @@ public class SettingsActivity extends AppCompatActivity
"ports_tcp_ip_retry_count",
"ports_tcp_ip_retry_delay",
"ports_sound_modem_preamble",
"ports_sound_modem_ptt_off_delay_ms"
"ports_sound_modem_ptt_off_delay_ms",
"aprs_is_tcpip_server_port"
};
private static final String[] _signedDecimalSettings = {

Wyświetl plik

@ -20,7 +20,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@androidx.room.Database(
version = 11,
version = 13,
entities = {LogItem.class, MessageItem.class, PositionItem.class, StationItem.class},
exportSchema = false
)

Wyświetl plik

@ -4,7 +4,7 @@ import androidx.room.Entity;
import androidx.room.Index;
import androidx.room.PrimaryKey;
@Entity(indices = {@Index(value = {"id", "srcCallsign"}, unique = true)})
@Entity(indices = {@Index(value = {"id", "srcCallsign", "dstCallsign", "ackId"}, unique = true)})
public class MessageItem {
@PrimaryKey(autoGenerate = true)
@ -14,7 +14,9 @@ public class MessageItem {
private String dstCallsign;
private String message;
private boolean needsAck;
private int ackNum;
private boolean isAcknowledged;
private int ackId;
private int retryCnt;
private boolean isTransmit;
public long getId() {
@ -35,7 +37,11 @@ public class MessageItem {
public boolean getNeedsAck() { return needsAck; }
public int getAckNum() { return ackNum; }
public int getAckId() { return ackId; }
public int getRetryCnt() { return this.retryCnt; }
public boolean getIsAcknowledged() { return this.isAcknowledged; }
public boolean getIsTransmit() { return isTransmit; }
@ -43,6 +49,8 @@ public class MessageItem {
this.id = id;
}
public void setRetryCnt(int retryCnt) { this.retryCnt = retryCnt; }
public void setTimestampEpoch(long timestampEpoch) {
this.timestampEpoch = timestampEpoch;
}
@ -57,8 +65,10 @@ public class MessageItem {
public void setNeedsAck(boolean needsAck) { this.needsAck = needsAck; }
public void setAckNum(int ackNum) { this.ackNum = ackNum; }
public void setAckId(int ackId) { this.ackId = ackId; }
public void setIsTransmit(boolean isTransmit) { this.isTransmit = isTransmit; }
public void setIsAcknowledged(boolean isAcknowledged) { this.isAcknowledged = isAcknowledged; }
}

Wyświetl plik

@ -75,6 +75,7 @@ public class MessageItemActivity extends AppCompatActivityWithServiceConnection
TextMessage textMessage = new TextMessage();
textMessage.dst = _groupName;
textMessage.text = messageEdit.getText().toString();
textMessage.ackId = 0;
getService().sendTextMessage(textMessage);
messageEdit.setText("");
}

Wyświetl plik

@ -13,6 +13,8 @@ import com.radio.codec2talkie.R;
import com.radio.codec2talkie.app.AppService;
import com.radio.codec2talkie.protocol.message.TextMessage;
import java.util.Locale;
public class MessageGroupDialogSendTo extends AlertDialog implements View.OnClickListener {
private final AppService _appService;
@ -44,8 +46,9 @@ public class MessageGroupDialogSendTo extends AlertDialog implements View.OnClic
assert targetEdit != null;
assert messageEdit != null;
TextMessage textMessage = new TextMessage();
textMessage.dst = targetEdit.getText().toString();
textMessage.dst = targetEdit.getText().toString().toUpperCase(Locale.ROOT);
textMessage.text = messageEdit.getText().toString();
textMessage.ackId = 0;
_appService.sendTextMessage(textMessage);
dismiss();
} else if (id == R.id.send_message_to_btn_cancel) {

Wyświetl plik

@ -338,7 +338,9 @@
<string name="aprs_is_settings_title">Internet APRS-IS</string>
<string name="aprs_is_settings_summary">Configure internet APRS-IS server connectivity</string>
<string name="aprs_is_tcpip_server_title">Server</string>
<string name="aprs_is_tcpip_server_summary">APRS-IS TCP server (port 14580) to connect</string>
<string name="aprs_is_tcpip_server_summary">APRS-IS TCP server to connect</string>
<string name="aprs_is_tcpip_server_port_title">Server port</string>
<string name="aprs_is_tcpip_server_port_summary">APRS-IS TCP server port to use</string>
<string name="aprs_is_enable_rx_gate_title">Enable APRS-IS RX gate</string>
<string name="aprs_is_enable_tx_gate_title">Enable APRS-IS TX gate</string>
<string name="aprs_is_enable_rx_gate_summary">Radio packets will be forwarded to APRS-IS</string>

Wyświetl plik

@ -18,6 +18,13 @@
app:defaultValue="euro.aprs2.net">
</EditTextPreference>
<EditTextPreference
app:key="aprs_is_tcpip_server_port"
app:title="@string/aprs_is_tcpip_server_port_title"
app:summary="@string/aprs_is_tcpip_server_port_summary"
app:defaultValue="14580">
</EditTextPreference>
<SwitchPreference
app:key="aprs_is_enable_rx_gate"
app:title="@string/aprs_is_enable_rx_gate_title"