kopia lustrzana https://github.com/N0BOY/FT8CN
586 wiersze
18 KiB
Java
Executable File
586 wiersze
18 KiB
Java
Executable File
package com.bg7yoz.ft8cn;
|
||
/**
|
||
* 常用变量。关于mainContext有内存泄漏的风险,以后解决。
|
||
* mainContext
|
||
*/
|
||
|
||
import android.annotation.SuppressLint;
|
||
import android.content.Context;
|
||
|
||
import androidx.lifecycle.MutableLiveData;
|
||
|
||
import com.bg7yoz.ft8cn.callsign.CallsignDatabase;
|
||
import com.bg7yoz.ft8cn.connector.ConnectMode;
|
||
import com.bg7yoz.ft8cn.database.ControlMode;
|
||
import com.bg7yoz.ft8cn.database.DatabaseOpr;
|
||
import com.bg7yoz.ft8cn.ft8transmit.QslRecordList;
|
||
import com.bg7yoz.ft8cn.log.QSLRecord;
|
||
import com.bg7yoz.ft8cn.rigs.BaseRigOperation;
|
||
import com.bg7yoz.ft8cn.timer.UtcTimer;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.HashMap;
|
||
import java.util.Iterator;
|
||
import java.util.Map;
|
||
import java.util.concurrent.ConcurrentHashMap;
|
||
|
||
|
||
public class GeneralVariables {
|
||
private static final String TAG = "GeneralVariables";
|
||
public static String VERSION = BuildConfig.VERSION_NAME;//版本号"0.62(Beta 4)";
|
||
public static String BUILD_DATE = BuildConfig.apkBuildTime;//编译的时间
|
||
public static int MESSAGE_COUNT = 3000;//消息的最大缓存数量
|
||
public static boolean saveSWLMessage=false;//保存解码消息开关
|
||
public static boolean saveSWL_QSO=false;//保存解码消息消息中的QSO开关
|
||
|
||
public static MutableLiveData<Float> mutableVolumePercent = new MutableLiveData<>();
|
||
public static float volumePercent = 0.5f;//播放音频的音量,是百分比
|
||
|
||
public static int flexMaxRfPower=10;//flex电台的最大发射功率
|
||
public static int flexMaxTunePower=10;//flex电台的最大调谐功率
|
||
|
||
private Context mainContext;
|
||
public static CallsignDatabase callsignDatabase = null;
|
||
|
||
public void setMainContext(Context context) {
|
||
mainContext = context;
|
||
}
|
||
|
||
public static boolean isChina = true;//语言是不是中国
|
||
public static boolean isTraditionalChinese = true;//语言是不是繁体中文
|
||
//public static double maxDist = 0;//最远距离
|
||
|
||
//各已经通联的分区列表
|
||
public static final Map<String, String> dxccMap = new HashMap<>();
|
||
public static final Map<Integer, Integer> cqMap = new HashMap<>();
|
||
public static final Map<Integer, Integer> ituMap = new HashMap<>();
|
||
|
||
private static final Map<String, Integer> excludedCallsigns = new HashMap<>();
|
||
|
||
/**
|
||
* 添加排除的字头
|
||
*
|
||
* @param callsigns 呼号
|
||
*/
|
||
public static synchronized void addExcludedCallsigns(String callsigns) {
|
||
excludedCallsigns.clear();
|
||
String[] s = callsigns.toUpperCase().replace(" ", ",")
|
||
.replace("|", ",")
|
||
.replace(",", ",").split(",");
|
||
for (int i = 0; i < s.length; i++) {
|
||
if (s[i].length() > 0) {
|
||
excludedCallsigns.put(s[i], 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 查找是否含有排除的字头
|
||
*
|
||
* @param callsign 呼号
|
||
* @return 是否
|
||
*/
|
||
public static synchronized boolean checkIsExcludeCallsign(String callsign) {
|
||
Iterator<String> iterator = excludedCallsigns.keySet().iterator();
|
||
while (iterator.hasNext()) {
|
||
String key = iterator.next();
|
||
if (callsign.toUpperCase().indexOf(key) == 0) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 获取排除呼号前缀的列表
|
||
*
|
||
* @return 列表
|
||
*/
|
||
public static synchronized String getExcludeCallsigns() {
|
||
StringBuilder calls = new StringBuilder();
|
||
Iterator<String> iterator = excludedCallsigns.keySet().iterator();
|
||
int i = 0;
|
||
while (iterator.hasNext()) {
|
||
String key = iterator.next();
|
||
if (i == 0) {
|
||
calls.append(key);
|
||
} else {
|
||
calls.append(",").append(key);
|
||
}
|
||
i++;
|
||
}
|
||
return calls.toString();
|
||
}
|
||
|
||
|
||
//通联记录列表,包括成功与不成功的
|
||
public static QslRecordList qslRecordList = new QslRecordList();
|
||
|
||
//此处有内存泄露警告,但Application Context不应该会内存泄露,所以注释掉
|
||
@SuppressLint("StaticFieldLeak")
|
||
private static GeneralVariables generalVariables = null;
|
||
|
||
public static GeneralVariables getInstance() {
|
||
if (generalVariables == null) {
|
||
generalVariables = new GeneralVariables();
|
||
}
|
||
return generalVariables;
|
||
}
|
||
|
||
public static Context getMainContext() {
|
||
return GeneralVariables.getInstance().mainContext;
|
||
}
|
||
|
||
|
||
public static MutableLiveData<String> mutableDebugMessage = new MutableLiveData<>();
|
||
public static int QUERY_FREQ_TIMEOUT = 2000;//轮询频率变化的时间间隔。2秒
|
||
public static int START_QUERY_FREQ_DELAY = 2000;//开始轮询频率的时间延迟
|
||
|
||
public static final int DEFAULT_LAUNCH_SUPERVISION = 10 * 60 * 1000;//发射监管默认值,10分钟
|
||
private static String myMaidenheadGrid = "";
|
||
public static MutableLiveData<String> mutableMyMaidenheadGrid = new MutableLiveData<>();
|
||
|
||
public static int connectMode = ConnectMode.USB_CABLE;//连接方式USB==0,BLUE_TOOTH==1
|
||
|
||
//public static String bluetoothDeviceAddress=null;//可以用于连接的蓝牙设备地址
|
||
|
||
|
||
//用于记录呼号于网格的对应关系 todo---应当把此处列表也放到后台追踪信息里
|
||
//public static ArrayList<CallsignMaidenheadGrid> callsignMaidenheadGrids=new ArrayList<>();
|
||
public static final Map<String, String> callsignAndGrids = new ConcurrentHashMap<>();
|
||
//private static final Map<String,String> callsignAndGrids=new HashMap<>();
|
||
|
||
public static String myCallsign = "";//我的呼号
|
||
public static String toModifier = "ADFG";//呼叫的修饰符
|
||
private static float baseFrequency = 1000;//声音频率
|
||
public static MutableLiveData<Float> mutableBaseFrequency = new MutableLiveData<>();
|
||
|
||
public static boolean synFrequency = false;//同频发射
|
||
public static int transmitDelay = 500;//发射延迟时间,这个时间也是给上一个周期的解码时间
|
||
public static int pttDelay = 100;//PTT的响应时间,在给电台PTT指令后,一般电台会有一个响应时间,此处默认是100毫秒
|
||
public static int civAddress = 0xa4;//civ地址
|
||
public static int baudRate = 19200;//波特率
|
||
public static long band = 14074000;//载波频段
|
||
public static int instructionSet = 0;//指令集,0:icom,1:yaesu 2 代,2:yaesu 3代。
|
||
public static int bandListIndex = -1;//电台波段的索引值
|
||
public static MutableLiveData<Integer> mutableBandChange = new MutableLiveData<>();//波段索引值变化
|
||
public static int controlMode = ControlMode.VOX;
|
||
public static int modelNo = 0;
|
||
public static int launchSupervision = DEFAULT_LAUNCH_SUPERVISION;//发射监管
|
||
public static long launchSupervisionStart = UtcTimer.getSystemTime();//自动发射的起始时间
|
||
public static int noReplyLimit = 0;//呼叫无回应次数0==忽略
|
||
|
||
public static int noReplyCount = 0;//没有回应的次数
|
||
|
||
//下面4个参数是ICOM网络方式连接的参数
|
||
public static String icomIp = "255.255.255.255";
|
||
public static int icomUdpPort = 50001;
|
||
public static String icomUserName = "ic705";
|
||
public static String icomPassword = "";
|
||
|
||
|
||
public static boolean autoFollowCQ = true;//自动关注CQ
|
||
public static boolean autoCallFollow = true;//自动呼叫关注的呼号
|
||
public static ArrayList<String> QSL_Callsign_list = new ArrayList<>();//QSL成功的呼号
|
||
public static ArrayList<String> QSL_Callsign_list_other_band = new ArrayList<>();//在其它波段QSL成功的呼号
|
||
|
||
|
||
public static final ArrayList<String> followCallsign = new ArrayList<>();//关注的呼号
|
||
|
||
public static ArrayList<Ft8Message> transmitMessages = new ArrayList<>();//放在呼叫界面,关注的列表
|
||
|
||
public static void setMyMaidenheadGrid(String grid) {
|
||
myMaidenheadGrid = grid;
|
||
mutableMyMaidenheadGrid.postValue(grid);
|
||
}
|
||
|
||
public static String getMyMaidenheadGrid() {
|
||
return myMaidenheadGrid;
|
||
}
|
||
|
||
public static float getBaseFrequency() {
|
||
return baseFrequency;
|
||
}
|
||
|
||
public static void setBaseFrequency(float baseFrequency) {
|
||
mutableBaseFrequency.postValue(baseFrequency);
|
||
GeneralVariables.baseFrequency = baseFrequency;
|
||
}
|
||
|
||
@SuppressLint("DefaultLocale")
|
||
public static String getBaseFrequencyStr() {
|
||
return String.format("%.0f", baseFrequency);
|
||
}
|
||
|
||
public static String getCivAddressStr() {
|
||
return String.format("%2X", civAddress);
|
||
}
|
||
|
||
public static String getTransmitDelayStr() {
|
||
return String.valueOf(transmitDelay);
|
||
}
|
||
|
||
public static String getBandString() {
|
||
return BaseRigOperation.getFrequencyAllInfo(band);
|
||
}
|
||
|
||
/**
|
||
* 查有没有通联成功的呼号
|
||
*
|
||
* @param callsign 呼号
|
||
* @return 是否存在
|
||
*/
|
||
public static boolean checkQSLCallsign(String callsign) {
|
||
return QSL_Callsign_list.contains(callsign);
|
||
}
|
||
|
||
/**
|
||
* 查别的波段有没有通联成功的呼号
|
||
*
|
||
* @param callsign 呼号
|
||
* @return 是否存在
|
||
*/
|
||
public static boolean checkQSLCallsign_OtherBand(String callsign) {
|
||
return QSL_Callsign_list_other_band.contains(callsign);
|
||
}
|
||
|
||
|
||
/**
|
||
* 查该呼号是不是在关注的呼号列表中
|
||
*
|
||
* @param callsign 呼号
|
||
* @return 是否存在
|
||
*/
|
||
public static boolean callsignInFollow(String callsign) {
|
||
return followCallsign.contains(callsign);
|
||
}
|
||
|
||
/**
|
||
* 向通联成功的呼号列表添加
|
||
*
|
||
* @param callsign 呼号
|
||
*/
|
||
public static void addQSLCallsign(String callsign) {
|
||
if (!checkQSLCallsign(callsign)) {
|
||
QSL_Callsign_list.add(callsign);
|
||
}
|
||
}
|
||
|
||
public static String getMyMaidenhead4Grid() {
|
||
if (myMaidenheadGrid.length() > 4) {
|
||
return myMaidenheadGrid.substring(0, 4);
|
||
}
|
||
return myMaidenheadGrid;
|
||
}
|
||
|
||
/**
|
||
* 自动程序运行起始时间
|
||
*/
|
||
public static void resetLaunchSupervision() {
|
||
launchSupervisionStart = UtcTimer.getSystemTime();
|
||
}
|
||
|
||
/**
|
||
* 或取自动程序的运行时长
|
||
*
|
||
* @return 毫秒
|
||
*/
|
||
public static int launchSupervisionCount() {
|
||
return (int) (UtcTimer.getSystemTime() - launchSupervisionStart);
|
||
}
|
||
|
||
public static boolean isLaunchSupervisionTimeout() {
|
||
if (launchSupervision == 0) return false;//0是不监管
|
||
return launchSupervisionCount() > launchSupervision;
|
||
}
|
||
|
||
/**
|
||
* 从extraInfo中查消息顺序
|
||
*
|
||
* @param extraInfo 消息中的扩展内容
|
||
* @return 返回消息序号
|
||
*/
|
||
public static int checkFunOrderByExtraInfo(String extraInfo) {
|
||
if (checkFun5(extraInfo)) return 5;
|
||
if (checkFun4(extraInfo)) return 4;
|
||
if (checkFun3(extraInfo)) return 3;
|
||
if (checkFun2(extraInfo)) return 2;
|
||
if (checkFun1(extraInfo)) return 1;
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 检查消息的序号,如果解析不出来,就-1
|
||
*
|
||
* @param message 消息
|
||
* @return 消息序号
|
||
*/
|
||
public static int checkFunOrder(Ft8Message message) {
|
||
if (message.checkIsCQ()) return 6;
|
||
return checkFunOrderByExtraInfo(message.extraInfo);
|
||
|
||
}
|
||
|
||
|
||
//是不是网格报告
|
||
public static boolean checkFun1(String extraInfo) {
|
||
//网格报告必须是4位,或没有网格
|
||
return (extraInfo.trim().matches("[A-Z][A-Z][0-9][0-9]") && !extraInfo.equals("RR73"))
|
||
|| (extraInfo.trim().length() == 0);
|
||
|
||
}
|
||
|
||
//是不是信号报告,如-10
|
||
public static boolean checkFun2(String extraInfo) {
|
||
if (extraInfo.trim().length() < 2) {
|
||
return false;
|
||
}//信号报告必须至少2位
|
||
try {
|
||
return Integer.parseInt(extraInfo.trim()) != 73;//如果是73,说明是消息6,不是消息2
|
||
//return true;
|
||
} catch (Exception e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//是不是带R的信号报告,如R-10
|
||
public static boolean checkFun3(String extraInfo) {
|
||
if (extraInfo.trim().length() < 3) {
|
||
return false;
|
||
}//带R信号报告必须至少3位
|
||
//第一位如果不是R,或者第二位是R,说明不是消息3
|
||
if ((extraInfo.trim().charAt(0) != 'R') || (extraInfo.trim().charAt(1) == 'R')) {
|
||
return false;
|
||
}
|
||
|
||
try {
|
||
Integer.parseInt(extraInfo.trim().substring(1));
|
||
return true;
|
||
} catch (Exception e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//是不是RRR或RR73值
|
||
public static boolean checkFun4(String extraInfo) {
|
||
return extraInfo.trim().equals("RR73") || extraInfo.trim().equals("RRR");
|
||
}
|
||
|
||
//是不是73值
|
||
public static boolean checkFun5(String extraInfo) {
|
||
return extraInfo.trim().equals("73");
|
||
}
|
||
|
||
|
||
/**
|
||
* 判断是不是信号报告,如果是,把值赋给 report
|
||
* @param extraInfo 消息扩展
|
||
* @return 信号报告值,没找到是-100
|
||
*/
|
||
public static int checkFun2_3(String extraInfo){
|
||
if (extraInfo.equals("73")) return -100;
|
||
if (extraInfo.matches("[R]?[+-]?[0-9]{1,2}")){
|
||
try {
|
||
return Integer.parseInt(extraInfo.replace("R",""));
|
||
} catch (Exception e) {
|
||
return -100;
|
||
}
|
||
}
|
||
return -100;
|
||
}
|
||
|
||
/**
|
||
* 判断是不是网格报告,如果是,把值赋给 report
|
||
* @param extraInfo 消息扩展
|
||
* @return 信号报告
|
||
*/
|
||
public static boolean checkFun1_6(String extraInfo){
|
||
return extraInfo.trim().matches("[A-Z][A-Z][0-9][0-9]")
|
||
&& !extraInfo.trim().equals("RR73");
|
||
}
|
||
/**
|
||
* 检查是否是通联结束:RRR、RR73、73
|
||
* @param extraInfo 消息后缀
|
||
* @return 是否
|
||
*/
|
||
public static boolean checkFun4_5(String extraInfo){
|
||
return extraInfo.trim().equals("RR73")
|
||
|| extraInfo.trim().equals("RRR")
|
||
||extraInfo.trim().equals("73");
|
||
}
|
||
|
||
/**
|
||
* 从String.xml中提取字符串
|
||
*
|
||
* @param id id
|
||
* @return 字符串
|
||
*/
|
||
public static String getStringFromResource(int id) {
|
||
if (getMainContext() != null) {
|
||
return getMainContext().getString(id);
|
||
} else {
|
||
return "";
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 把已经通联的DXCC分区添加到集合中
|
||
*
|
||
* @param dxccPrefix DXCC前缀
|
||
*/
|
||
public static void addDxcc(String dxccPrefix) {
|
||
dxccMap.put(dxccPrefix, dxccPrefix);
|
||
}
|
||
|
||
/**
|
||
* 查看是不是已经通联的DXCC分区
|
||
*
|
||
* @param dxccPrefix DXCC前缀
|
||
* @return 是否
|
||
*/
|
||
public static boolean getDxccByPrefix(String dxccPrefix) {
|
||
return dxccMap.containsKey(dxccPrefix);
|
||
}
|
||
|
||
/**
|
||
* 把CQ分区加到列表里
|
||
*
|
||
* @param cqZone cq分区编号
|
||
*/
|
||
public static void addCqZone(int cqZone) {
|
||
cqMap.put(cqZone, cqZone);
|
||
}
|
||
|
||
/**
|
||
* 查是否存在已经通联的CQ分区
|
||
*
|
||
* @param cq cq分区编号
|
||
* @return 是否存在
|
||
*/
|
||
public static boolean getCqZoneById(int cq) {
|
||
return cqMap.containsKey(cq);
|
||
}
|
||
|
||
/**
|
||
* 把itu分区添加到已通联的ITU列表中
|
||
*
|
||
* @param itu itu编号
|
||
*/
|
||
public static void addItuZone(int itu) {
|
||
ituMap.put(itu, itu);
|
||
}
|
||
|
||
/**
|
||
* 查Itu分区在不在已通联的列表中
|
||
*
|
||
* @param itu itu编号
|
||
* @return 是否存在
|
||
*/
|
||
public static boolean getItuZoneById(int itu) {
|
||
return ituMap.containsKey(itu);
|
||
}
|
||
|
||
//用于触发新的网格
|
||
public static MutableLiveData<String> mutableNewGrid = new MutableLiveData<>();
|
||
|
||
/**
|
||
* 把呼号与网格的对应关系添加到呼号--网格对应表,
|
||
*
|
||
* @param callsign 呼号
|
||
* @param grid 网格
|
||
*/
|
||
public static void addCallsignAndGrid(String callsign, String grid) {
|
||
if (grid.length() >= 4) {
|
||
callsignAndGrids.put(callsign, grid);
|
||
mutableNewGrid.postValue(grid);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 呼号--网格对应表。以呼号查网格
|
||
* 如果内存中没有,应当到数据库中查一下。
|
||
*
|
||
* @param callsign 呼号
|
||
* @return 是否有对应的网格
|
||
*/
|
||
public static boolean getCallsignHasGrid(String callsign) {
|
||
return callsignAndGrids.containsKey(callsign);
|
||
}
|
||
|
||
/**
|
||
* 呼号--网格对应表。以呼号查网格,条件是呼号和网格都对应的上。
|
||
* 此函数的目的是,为了更新对应表的数据库
|
||
*
|
||
* @param callsign 呼号
|
||
* @param grid 网格
|
||
* @return 是否有对应的网格
|
||
*/
|
||
public static boolean getCallsignHasGrid(String callsign, String grid) {
|
||
if (!callsignAndGrids.containsKey(callsign)) return false;//说明根本没有这个呼号
|
||
String s = callsignAndGrids.get(callsign);
|
||
if (s == null) return false;
|
||
return s.equals(grid);
|
||
}
|
||
|
||
public static String getGridByCallsign(String callsign, DatabaseOpr db) {
|
||
String s = callsign.replace("<", "").replace(">", "");
|
||
if (getCallsignHasGrid(s)) {
|
||
return callsignAndGrids.get(s);
|
||
} else {
|
||
db.getCallsignQTH(callsign);
|
||
return "";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 遍历呼号--网格对应表,生成HTML
|
||
*
|
||
* @return HTML
|
||
*/
|
||
public static String getCallsignAndGridToHTML() {
|
||
StringBuilder result = new StringBuilder();
|
||
int order = 0;
|
||
for (String key : callsignAndGrids.keySet()) {
|
||
order++;
|
||
if (order % 2 == 0) {
|
||
result.append("<tr class=\"bbb\" >");
|
||
} else {
|
||
result.append("<tr>");
|
||
}
|
||
result.append("<td align=center class=\"default\" >");
|
||
result.append(key);
|
||
result.append("</td>\n");
|
||
result.append("<td align=center class=\"default\" >");
|
||
result.append(callsignAndGrids.get(key));
|
||
result.append("</tr>\n");
|
||
|
||
}
|
||
return result.toString();
|
||
|
||
}
|
||
|
||
public static synchronized void deleteArrayListMore(ArrayList<Ft8Message> list) {
|
||
if (list.size() > GeneralVariables.MESSAGE_COUNT) {
|
||
while (list.size() > GeneralVariables.MESSAGE_COUNT) {
|
||
list.remove(0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 判断是否为整数
|
||
*
|
||
* @param str 传入的字符串
|
||
* @return 是整数返回true, 否则返回false
|
||
*/
|
||
|
||
public static boolean isInteger(String str) {
|
||
if (str != null && !"".equals(str.trim()))
|
||
return str.matches("^[0-9]*$");
|
||
else
|
||
return false;
|
||
}
|
||
|
||
}
|