codec2_talkie/codec2talkie/src/main/java/com/radio/codec2talkie/protocol/aprs/AprsDataTextMessage.java

132 wiersze
3.9 KiB
Java

package com.radio.codec2talkie.protocol.aprs;
import com.radio.codec2talkie.protocol.message.TextMessage;
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;
public class AprsDataTextMessage implements AprsData {
public String srcCallsign;
public String dstCallsign;
public String digipath;
public String textMessage;
public Integer ackId;
private boolean _isValid;
@Override
public boolean isPositionReport() {
return false;
}
@Override
public boolean isTextMessage() {
return true;
}
@Override
public void fromPosition(Position position) {
_isValid = false;
}
@Override
public void fromTextMessage(TextMessage textMessage) {
this.dstCallsign = textMessage.dst;
this.textMessage = textMessage.text;
this.digipath = textMessage.digipath;
this.ackId = textMessage.ackId;
_isValid = true;
}
@Override
public Position toPosition() {
return null;
}
@Override
public TextMessage toTextMessage() {
TextMessage textMessage = new TextMessage();
textMessage.src = this.srcCallsign;
textMessage.dst = this.dstCallsign;
textMessage.digipath = this.digipath;
textMessage.text = this.textMessage;
textMessage.ackId = this.ackId;
return textMessage;
}
@Override
public void fromBinary(String srcCallsign, String dstCallsign, String digipath, byte[] infoData) {
_isValid = false;
if (infoData.length < 10) return;
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);
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("^.+[{](\\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 {
this.textMessage = stringMessage;
}
}
// TODO, telemetry, make subclass from message, extend and extract values
if (this.textMessage != null)
_isValid = !isTelemetry(this.textMessage);
}
@Override
public byte[] toBinary() {
return (ackId > 0)
? String.format(Locale.US, ":%-9s:%s{%d", dstCallsign, textMessage, ackId).getBytes()
: String.format(":%-9s:%s", dstCallsign, textMessage).getBytes();
}
@Override
public boolean isValid() {
return _isValid;
}
private boolean isTelemetry(String textMessage) {
Pattern p = Pattern.compile("^(EQNS|PARM|UNIT|BITS)[.].+$", Pattern.DOTALL);
Matcher m = p.matcher(textMessage);
return m.matches();
}
}