kopia lustrzana https://github.com/sh123/codec2_talkie
Porównaj commity
3 Commity
e6a05091d9
...
64e6b7f265
Autor | SHA1 | Data |
---|---|---|
sh123 | 64e6b7f265 | |
sh123 | 854bd629da | |
sh123 | 1edf1c4c51 |
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
||||
|
|
|
@ -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("");
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
Ładowanie…
Reference in New Issue