package com.radio.codec2talkie.protocol.ax25; import androidx.annotation.NonNull; import java.nio.ByteBuffer; public class AX25Callsign { public static int CallsignMaxSize = 7; public String callsign; public int ssid; public boolean isValid; public boolean isLast = false; public AX25Callsign() {} public AX25Callsign(String callsign, String ssid) { this.callsign = callsign; this.ssid = Integer.parseInt(ssid); } public static String formatCallsign(String callsign, String ssid) { return String.format("%s-%s", callsign, ssid); } public void fromString(String inputCallsignWithSsid) { isValid = false; if (inputCallsignWithSsid == null) return; // WIDE1* String callsignWithSsid = inputCallsignWithSsid.replace("*", ""); // ABCDEF-XX if (callsignWithSsid.length() > CallsignMaxSize + 2 || callsignWithSsid.length() == 0) return; int delimiterIndex = callsignWithSsid.indexOf('-'); // ABCDEF- if (delimiterIndex != -1 && delimiterIndex == callsignWithSsid.length() - 1) return; callsign = callsignWithSsid; ssid = 0; if (delimiterIndex == -1) { // ABCDEF if (callsign.length() >= CallsignMaxSize) return; } else { callsign = callsignWithSsid.substring(0, delimiterIndex); try { ssid = Integer.parseInt(callsignWithSsid.substring(delimiterIndex + 1)); } catch(NumberFormatException e) { return; } } isValid = true; } public void fromBinary(byte[] data) { isValid = false; if (data == null) return; if (data.length != CallsignMaxSize) return; StringBuilder buffer = new StringBuilder(); for (int i = 0; i < data.length - 1; i++) { int d = (data[i] & 0xff) >>> 1; char c = (char)d; if (c == ' '){ break; } else { buffer.append(c); } } callsign = buffer.toString(); byte lastByte = data[data.length - 1]; isLast = (lastByte & 0x01) == 1; ssid = (lastByte >>> 1) & 0x0f; if (callsign.length() == 0) return; isValid = true; } @NonNull public String toString() { String callsignPlusSsid = callsign; if (ssid == 0) { if (isWide()) callsignPlusSsid += "*"; } else { callsignPlusSsid += "-" + ssid; } return callsignPlusSsid; } public byte[] toBinary() { ByteBuffer buffer = ByteBuffer.allocate(CallsignMaxSize); for (int i = 0; i < CallsignMaxSize - 1; i++) { if (i < callsign.length()) { byte c = (byte) callsign.charAt(i); buffer.put((byte)(c << 1)); } else { // append ' ' for short callsigns buffer.put((byte)(0x20 << 1)); } } byte binSsid = (byte)(ssid << 1); if (isLast) { binSsid |= 1; } buffer.put(binSsid); // return buffer.flip(); byte[] b = new byte[buffer.remaining()]; buffer.get(b); return b; } public boolean isWide() { return callsign.toUpperCase().startsWith("WIDE"); } public boolean isTrace() { return callsign.toUpperCase().startsWith("TRACE"); } public boolean isSoftware() { return callsign.toUpperCase().matches("^(AP)[A-Z]{1,4}$"); } public boolean isPath() { return isWide(); } public boolean digiRepeatCallsign() { if (ssid > 0) { ssid -= 1; return true; } return false; } public boolean digiRepeat() { if (isPath()) { return digiRepeatCallsign(); } return false; } }