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

242 wiersze
8.8 KiB
Java

package com.radio.codec2talkie.protocol;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import androidx.preference.PreferenceManager;
import com.radio.codec2talkie.protocol.ax25.AX25Callsign;
import com.radio.codec2talkie.protocol.ax25.AX25Packet;
import com.radio.codec2talkie.protocol.message.TextMessage;
import com.radio.codec2talkie.protocol.position.Position;
import com.radio.codec2talkie.settings.PreferenceKeys;
import com.radio.codec2talkie.settings.SettingsWrapper;
import com.radio.codec2talkie.transport.Transport;
import java.io.IOException;
public class Ax25 implements Protocol {
private static final String TAG = Ax25.class.getSimpleName();
final Protocol _childProtocol;
private String _myCallsign;
private String _digipath;
private boolean _isVoax25Enabled;
private boolean _isDigiRepeaterEnabled;
private boolean _useTextPackets;
private ProtocolCallback _parentProtocolCallback;
public Ax25(Protocol childProtocol) {
_childProtocol = childProtocol;
}
@Override
public void initialize(Transport transport, Context context, ProtocolCallback protocolCallback) throws IOException {
_parentProtocolCallback = protocolCallback;
_childProtocol.initialize(transport, context, _protocolCallback);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
_myCallsign = AX25Callsign.formatCallsign(
sharedPreferences.getString(PreferenceKeys.AX25_CALLSIGN, "NOCALL").toUpperCase(),
sharedPreferences.getString(PreferenceKeys.AX25_SSID, "0"));
// NOTE, may need to pass through sendData/sendAudio
_digipath = sharedPreferences.getString(PreferenceKeys.AX25_DIGIPATH, "").toUpperCase();
_isVoax25Enabled = SettingsWrapper.isVoax25Enabled(sharedPreferences);
_useTextPackets = SettingsWrapper.isTextPacketsEnabled(sharedPreferences);
_isDigiRepeaterEnabled = sharedPreferences.getBoolean(PreferenceKeys.AX25_DIGIREPEATER_ENABLED, false);
}
@Override
public int getPcmAudioRecordBufferSize() {
return _childProtocol.getPcmAudioRecordBufferSize();
}
@Override
public void sendCompressedAudio(String src, String dst, byte[] frame) throws IOException {
if (_isVoax25Enabled) {
AX25Packet ax25Packet = new AX25Packet();
ax25Packet.src = src;
ax25Packet.dst = dst;
ax25Packet.digipath = _digipath;
ax25Packet.isAudio = true;
ax25Packet.rawData = frame;
byte[] ax25Frame = ax25Packet.toBinary();
if (ax25Frame == null) {
Log.e(TAG, "Cannot convert AX.25 voice packet to binary");
_parentProtocolCallback.onProtocolTxError();
} else {
_childProtocol.sendCompressedAudio(src, dst, ax25Frame);
}
} else {
_childProtocol.sendCompressedAudio(src, dst, frame);
}
}
@Override
public void sendTextMessage(TextMessage textMessage) throws IOException {
_childProtocol.sendTextMessage(textMessage);
}
@Override
public void sendPcmAudio(String src, String dst, short[] pcmFrame) throws IOException {
_childProtocol.sendPcmAudio(src, dst, pcmFrame);
}
@Override
public void sendData(String src, String dst, String path, byte[] dataPacket) throws IOException {
_parentProtocolCallback.onTransmitData(src, dst, _digipath, dataPacket);
AX25Packet ax25Packet = new AX25Packet();
ax25Packet.src = src;
ax25Packet.dst = dst;
ax25Packet.digipath = path == null ? _digipath : path;
ax25Packet.isAudio = false;
ax25Packet.rawData = dataPacket;
byte[] ax25Frame = _useTextPackets ? ax25Packet.toTextBinary() : ax25Packet.toBinary();
if (ax25Frame == null) {
Log.e(TAG, "Cannot convert AX.25 data packet to binary");
_parentProtocolCallback.onProtocolTxError();
} else {
_childProtocol.sendData(src, dst, ax25Packet.digipath, ax25Frame);
_parentProtocolCallback.onTransmitLog(ax25Packet.toString());
}
}
@Override
public boolean receive() throws IOException {
return _childProtocol.receive();
}
ProtocolCallback _protocolCallback = new ProtocolCallback() {
@Override
protected void onReceivePosition(Position position) {
_parentProtocolCallback.onReceivePosition(position);
}
@Override
protected void onReceivePcmAudio(String src, String dst, short[] pcmFrame) {
_parentProtocolCallback.onReceivePcmAudio(src, dst, pcmFrame);
}
@Override
protected void onReceiveCompressedAudio(String src, String dst, byte[] audioFrames) {
AX25Packet ax25Data = new AX25Packet();
ax25Data.fromBinary(audioFrames);
if (ax25Data.isValid) {
if (ax25Data.isAudio) {
_parentProtocolCallback.onReceiveCompressedAudio(ax25Data.src, ax25Data.dst, ax25Data.rawData);
} else {
_parentProtocolCallback.onReceiveLog(ax25Data.toString());
_parentProtocolCallback.onReceiveData(ax25Data.src, ax25Data.dst, ax25Data.digipath, ax25Data.rawData);
if (_isDigiRepeaterEnabled) digiRepeat(ax25Data);
}
} else {
// fallback to raw audio if ax25 frame is invalid
_parentProtocolCallback.onReceiveCompressedAudio(src, dst, audioFrames);
}
}
@Override
protected void onReceiveTextMessage(TextMessage textMessage) {
_parentProtocolCallback.onReceiveTextMessage(textMessage);
}
@Override
protected void onReceiveData(String src, String dst, String path, byte[] data) {
_parentProtocolCallback.onReceiveData(src, dst, path, data);
}
@Override
protected void onReceiveSignalLevel(short rssi, short snr) {
_parentProtocolCallback.onReceiveSignalLevel(rssi, snr);
}
@Override
protected void onReceiveTelemetry(int batVoltage) {
_parentProtocolCallback.onReceiveTelemetry(batVoltage);
}
@Override
protected void onReceiveLog(String logData) {
_parentProtocolCallback.onReceiveLog(logData);
}
@Override
protected void onTransmitPcmAudio(String src, String dst, short[] frame) {
_parentProtocolCallback.onTransmitPcmAudio(src, dst, frame);
}
@Override
protected void onTransmitCompressedAudio(String src, String dst, byte[] frame) {
_parentProtocolCallback.onTransmitCompressedAudio(src, dst, frame);
}
@Override
protected void onTransmitTextMessage(TextMessage textMessage) {
_parentProtocolCallback.onTransmitTextMessage(textMessage);
}
@Override
protected void onTransmitPosition(Position position) {
_parentProtocolCallback.onTransmitPosition(position);
}
@Override
protected void onTransmitData(String src, String dst, String path, byte[] data) {
_parentProtocolCallback.onTransmitData(src, dst, path, data);
}
@Override
protected void onTransmitLog(String logData) {
_parentProtocolCallback.onTransmitLog(logData);
}
@Override
protected void onProtocolRxError() {
_parentProtocolCallback.onProtocolRxError();
}
@Override
protected void onProtocolTxError() {
_parentProtocolCallback.onProtocolTxError();
}
};
@Override
public void sendPosition(Position position) throws IOException {
_childProtocol.sendPosition(position);
}
@Override
public void flush() throws IOException {
_childProtocol.flush();
}
@Override
public void close() {
_childProtocol.close();
}
private void digiRepeat(AX25Packet ax25Packet) {
if (ax25Packet.src.equals(_myCallsign)) return;
if (!ax25Packet.digiRepeat()) return;
byte[] ax25Frame = ax25Packet.toBinary();
if (ax25Frame == null) {
Log.e(TAG, "Cannot convert AX.25 digi repeated packet to binary");
_parentProtocolCallback.onProtocolTxError();
} else {
try {
_childProtocol.sendData(ax25Packet.src, ax25Packet.dst, ax25Packet.digipath, ax25Frame);
} catch (IOException e) {
Log.e(TAG, "Cannot send AX.25 digi repeated packet");
e.printStackTrace();
_parentProtocolCallback.onProtocolTxError();
return;
}
_parentProtocolCallback.onTransmitLog(ax25Packet.toString());
}
}
}