codec2_talkie/codec2talkie/src/main/java/com/radio/codec2talkie/protocol/Aprs.java

262 wiersze
10 KiB
Java
Czysty Zwykły widok Historia

2022-06-29 19:23:02 +00:00
package com.radio.codec2talkie.protocol;
import android.content.Context;
2022-06-29 21:06:59 +00:00
import android.content.SharedPreferences;
import android.util.Log;
2022-06-29 19:23:02 +00:00
2022-06-29 21:06:59 +00:00
import androidx.preference.PreferenceManager;
2022-07-01 14:47:37 +00:00
import com.radio.codec2talkie.protocol.aprs.AprsCallsign;
import com.radio.codec2talkie.protocol.aprs.AprsData;
import com.radio.codec2talkie.protocol.aprs.AprsDataFactory;
import com.radio.codec2talkie.protocol.aprs.AprsDataType;
2022-07-18 17:17:40 +00:00
import com.radio.codec2talkie.protocol.message.TextMessage;
import com.radio.codec2talkie.protocol.position.Position;
import com.radio.codec2talkie.protocol.ax25.AX25Callsign;
2022-06-29 21:06:59 +00:00
import com.radio.codec2talkie.settings.PreferenceKeys;
2022-08-14 19:22:04 +00:00
import com.radio.codec2talkie.settings.SettingsWrapper;
2022-06-29 19:23:02 +00:00
import com.radio.codec2talkie.transport.Transport;
import java.io.IOException;
public class Aprs implements Protocol {
2023-06-30 11:19:18 +00:00
public static final String APRS_ID = "APCTLK";
private static final String TAG = Aprs.class.getSimpleName();
2022-06-29 19:23:02 +00:00
private final Protocol _childProtocol;
2022-07-03 09:05:00 +00:00
private ProtocolCallback _parentProtocolCallback;
2022-06-29 21:06:59 +00:00
private String _srcCallsign;
private String _dstCallsign;
private String _symbolCode;
private String _status;
private String _comment;
2022-07-02 20:51:17 +00:00
private int _miceDigipath;
private boolean _isVoax25Enabled;
private boolean _isCompressed;
2022-07-02 14:28:32 +00:00
private boolean _isBearingCourseEnabled;
private boolean _isAltitudeEnabled;
2022-07-02 13:57:03 +00:00
private int _privacyLevel;
2022-06-29 21:06:59 +00:00
private AprsDataType _positionDataType;
2022-07-01 14:18:37 +00:00
2022-06-29 19:23:02 +00:00
public Aprs(Protocol childProtocol) {
_childProtocol = childProtocol;
}
@Override
2022-07-03 09:05:00 +00:00
public void initialize(Transport transport, Context context, ProtocolCallback protocolCallback) throws IOException {
_parentProtocolCallback = protocolCallback;
2022-07-01 14:18:37 +00:00
_childProtocol.initialize(transport, context, _protocolCallback);
2022-06-29 21:06:59 +00:00
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
2022-08-14 19:22:04 +00:00
_isVoax25Enabled = SettingsWrapper.isVoax25Enabled(sharedPreferences);
_srcCallsign = AX25Callsign.formatCallsign(
2022-07-25 20:29:34 +00:00
sharedPreferences.getString(PreferenceKeys.AX25_CALLSIGN, "NOCALL").toUpperCase(),
sharedPreferences.getString(PreferenceKeys.AX25_SSID, "0"));
2023-06-30 11:19:18 +00:00
_dstCallsign = APRS_ID;
_symbolCode = sharedPreferences.getString(PreferenceKeys.APRS_SYMBOL, "/[");
String packetFormat = sharedPreferences.getString(PreferenceKeys.APRS_LOCATION_PACKET_FORMAT, "uncompressed");
_status = sharedPreferences.getString(PreferenceKeys.APRS_LOCATION_MIC_E_MESSAGE_TYPE, "off_duty");
_comment = sharedPreferences.getString(PreferenceKeys.APRS_COMMENT, "off_duty");
2022-07-02 13:57:03 +00:00
_privacyLevel = Integer.parseInt(sharedPreferences.getString(PreferenceKeys.APRS_PRIVACY_POSITION_AMBIGUITY, "0"));
2022-07-02 14:28:32 +00:00
_isAltitudeEnabled = sharedPreferences.getBoolean(PreferenceKeys.APRS_PRIVACY_ALTITUDE_ENABLED, false);
_isBearingCourseEnabled = sharedPreferences.getBoolean(PreferenceKeys.APRS_PRIVACY_SPEED_ENABLED, false);
2022-07-02 20:51:17 +00:00
_miceDigipath = Integer.parseInt(sharedPreferences.getString(PreferenceKeys.APRS_LOCATION_MIC_E_DIGIPATH, "0"));
_isCompressed = packetFormat.equals("compressed");
AprsDataType.DataType dataType = packetFormat.equals("mic_e") ?
AprsDataType.DataType.MIC_E : AprsDataType.DataType.POSITION_WITHOUT_TIMESTAMP_MSG;
_positionDataType = new AprsDataType(dataType);
2022-06-29 19:23:02 +00:00
}
@Override
2022-08-13 17:48:45 +00:00
public int getPcmAudioRecordBufferSize() {
return _childProtocol.getPcmAudioRecordBufferSize();
2022-06-29 19:23:02 +00:00
}
@Override
2023-12-09 12:27:49 +00:00
public void sendCompressedAudio(String src, String dst, byte[] frame) throws IOException {
_childProtocol.sendCompressedAudio(src, dst, frame);
2022-06-29 19:23:02 +00:00
}
2022-07-18 17:17:40 +00:00
@Override
public void sendTextMessage(TextMessage textMessage) throws IOException {
AprsDataType aprsDataType = new AprsDataType(AprsDataType.DataType.MESSAGE);
AprsData aprsData = AprsDataFactory.create(aprsDataType);
assert aprsData != null;
aprsData.fromTextMessage(textMessage);
if (aprsData.isValid()) {
2022-07-18 19:24:48 +00:00
textMessage.src = _srcCallsign;
sendData(_srcCallsign, _dstCallsign, null, aprsData.toBinary());
2022-07-18 19:24:48 +00:00
_parentProtocolCallback.onTransmitTextMessage(textMessage);
2022-07-18 17:17:40 +00:00
} else {
Log.e(TAG, "Invalid APRS message");
_parentProtocolCallback.onProtocolTxError();
}
}
2022-06-29 19:23:02 +00:00
@Override
2023-12-09 12:27:49 +00:00
public void sendPcmAudio(String src, String dst, short[] pcmFrame) throws IOException {
2022-07-01 14:18:37 +00:00
if (_isVoax25Enabled) {
2023-12-09 12:27:49 +00:00
_childProtocol.sendPcmAudio(src == null ? _srcCallsign : src, dst == null ? _dstCallsign : dst, pcmFrame);
2022-07-01 14:18:37 +00:00
} else {
2023-12-09 12:27:49 +00:00
_childProtocol.sendPcmAudio(src, dst, pcmFrame);
2022-07-01 14:18:37 +00:00
}
2022-06-29 19:23:02 +00:00
}
@Override
public void sendData(String src, String dst, String path, byte[] dataPacket) throws IOException {
_childProtocol.sendData(src == null ? _srcCallsign : src, dst == null ? _dstCallsign : dst, path, dataPacket);
2022-06-29 19:23:02 +00:00
}
@Override
2022-07-01 14:18:37 +00:00
public boolean receive() throws IOException {
return _childProtocol.receive();
2022-06-29 19:23:02 +00:00
}
2022-07-03 09:05:00 +00:00
ProtocolCallback _protocolCallback = new ProtocolCallback() {
2022-07-01 14:18:37 +00:00
@Override
protected void onReceivePosition(Position position) {
2022-08-13 17:48:45 +00:00
_parentProtocolCallback.onReceivePosition(position);
2022-07-01 14:18:37 +00:00
}
@Override
2023-12-09 12:27:49 +00:00
protected void onReceivePcmAudio(String src, String dst, short[] pcmFrame) {
2022-07-02 14:10:44 +00:00
String dstCallsign = new AprsCallsign(dst).isSoftware() ? "*" : dst;
2023-12-09 12:27:49 +00:00
_parentProtocolCallback.onReceivePcmAudio(src, dstCallsign, pcmFrame);
2022-07-01 14:18:37 +00:00
}
@Override
2023-12-09 12:27:49 +00:00
protected void onReceiveCompressedAudio(String src, String dst, byte[] audioFrame) {
_parentProtocolCallback.onReceiveCompressedAudio(src, dst, audioFrame);
2022-07-01 14:18:37 +00:00
}
2022-07-18 19:24:48 +00:00
@Override
protected void onReceiveTextMessage(TextMessage textMessage) {
_parentProtocolCallback.onReceiveTextMessage(textMessage);
}
2022-07-01 14:18:37 +00:00
@Override
protected void onReceiveData(String src, String dst, String path, byte[] data) {
2022-07-18 19:24:48 +00:00
if (data.length == 0) return;
2022-08-20 12:52:10 +00:00
AprsData aprsData = AprsDataFactory.fromBinary(src, dst, path, data);
if (aprsData != null && aprsData.isValid()) {
2023-07-02 08:10:45 +00:00
if (aprsData.isTextMessage()) {
2022-07-18 19:24:48 +00:00
TextMessage textMessage = aprsData.toTextMessage();
_parentProtocolCallback.onReceiveTextMessage(textMessage);
return;
2023-07-02 08:10:45 +00:00
} else if (aprsData.isPositionReport()) {
2022-07-18 19:24:48 +00:00
Position position = aprsData.toPosition();
if (position != null) {
_parentProtocolCallback.onReceivePosition(position);
return;
}
}
}
_parentProtocolCallback.onReceiveData(src, dst, path, data);
2022-07-01 14:18:37 +00:00
}
@Override
protected void onReceiveSignalLevel(short rssi, short snr) {
2022-07-03 09:05:00 +00:00
_parentProtocolCallback.onReceiveSignalLevel(rssi, snr);
2022-07-01 14:18:37 +00:00
}
@Override
protected void onReceiveTelemetry(int batVoltage) {
_parentProtocolCallback.onReceiveTelemetry(batVoltage);
}
2022-07-01 14:39:45 +00:00
@Override
protected void onReceiveLog(String logData) {
2022-07-03 09:05:00 +00:00
_parentProtocolCallback.onReceiveLog(logData);
2022-07-01 14:39:45 +00:00
}
2022-07-01 14:18:37 +00:00
@Override
2023-12-09 12:27:49 +00:00
protected void onTransmitPcmAudio(String src, String dst, short[] frame) {
2022-07-02 14:10:44 +00:00
String dstCallsign = new AprsCallsign(dst).isSoftware() ? "*" : dst;
2023-12-09 12:27:49 +00:00
_parentProtocolCallback.onTransmitPcmAudio(src, dstCallsign, frame);
2022-07-01 14:18:37 +00:00
}
@Override
2023-12-09 12:27:49 +00:00
protected void onTransmitCompressedAudio(String src, String dst, byte[] frame) {
_parentProtocolCallback.onTransmitCompressedAudio(src, dst, frame);
2022-07-01 14:18:37 +00:00
}
2022-07-18 19:24:48 +00:00
@Override
protected void onTransmitTextMessage(TextMessage textMessage) {
_parentProtocolCallback.onTransmitTextMessage(textMessage);
}
2022-07-31 14:03:31 +00:00
@Override
protected void onTransmitPosition(Position position) {
2022-08-13 17:48:45 +00:00
_parentProtocolCallback.onTransmitPosition(position);
2022-07-31 14:03:31 +00:00
}
2022-07-01 14:18:37 +00:00
@Override
protected void onTransmitData(String src, String dst, String path, byte[] data) {
_parentProtocolCallback.onTransmitData(src, dst, path, data);
2022-07-01 14:18:37 +00:00
}
2022-07-01 14:39:45 +00:00
@Override
protected void onTransmitLog(String logData) {
2022-07-03 09:05:00 +00:00
_parentProtocolCallback.onTransmitLog(logData);
2022-07-01 14:39:45 +00:00
}
2022-07-01 14:18:37 +00:00
@Override
protected void onProtocolRxError() {
2022-07-03 09:05:00 +00:00
_parentProtocolCallback.onProtocolRxError();
2022-07-01 14:18:37 +00:00
}
@Override
protected void onProtocolTxError() {
2022-07-03 09:05:00 +00:00
_parentProtocolCallback.onProtocolTxError();
2022-07-01 14:18:37 +00:00
}
};
2022-06-29 19:23:02 +00:00
@Override
public void sendPosition(Position position) throws IOException {
position.dstCallsign = _dstCallsign;
position.srcCallsign = _srcCallsign;
position.symbolCode = _symbolCode;
position.comment = _comment;
position.status = _status;
position.isCompressed = _isCompressed;
2022-07-02 13:57:03 +00:00
position.privacyLevel = _privacyLevel;
2022-07-02 14:28:32 +00:00
position.isSpeedBearingEnabled = _isBearingCourseEnabled;
position.isAltitudeEnabled = _isAltitudeEnabled;
2022-07-02 20:51:17 +00:00
position.extDigipathSsid = _miceDigipath;
AprsData aprsData = AprsDataFactory.create(_positionDataType);
if (aprsData != null) {
2022-07-03 17:49:11 +00:00
try {
aprsData.fromPosition(position);
} catch (Exception e) {
e.printStackTrace();
_parentProtocolCallback.onProtocolTxError();
return;
}
if (aprsData.isValid()) {
sendData(position.srcCallsign, position.dstCallsign, null, aprsData.toBinary());
2022-07-31 14:03:31 +00:00
_parentProtocolCallback.onTransmitPosition(position);
} else {
2022-07-03 17:49:11 +00:00
Log.e(TAG, "Invalid APRS data");
_parentProtocolCallback.onProtocolTxError();
}
}
2022-06-29 19:23:02 +00:00
}
@Override
public void flush() throws IOException {
_childProtocol.flush();
}
@Override
public void close() {
_childProtocol.close();
}
}