FT8CN/ft8CN/app/src/main/java/com/bg7yoz/ft8cn/MainViewModel.java

893 wiersze
36 KiB
Java
Executable File
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.bg7yoz.ft8cn;
/**
* -----2022.5.6-----
* MainViewModel类用于解码FT8信号以及保存与解码有关的变量数据。生存于APP的整个生命周期。
* 1.解码的总条数。decoded_counter和mutable_Decoded_Counter。
* 2.解码消息的列表。消息以Ft8Message展示列表用ArrayList泛型实现。ft8MessagesmutableFt8MessageList。
* 3.解码和录音都需要时间同步也就是以UTC时间的每15秒为一个周期。同步事件的触发由UtcTimer类来实现。
* 录音方法runRecode解码暂时用testFt8实现后续应改为类方式。--------TODO------------
* 4.当前的UTC时间。timerSec更新频率心跳频率由UtcTimer确定暂定100毫秒。
* <p>
* 5.通过类方法getInstance获取当前的MainViewModel的实例确保有唯一的实例。
* 6.用HamAudioRecorder类实现录音目前只实现录音成文件然后读取文件的数据给解码模块后面要改成直接给数组的方式----TO DO---
* <p>
* 7.解码采用JNI接口调用原生C语言。调用接口名时ft8cn由cpp文件夹下的CMakeLists.txt维护。各函数的调用接口在decode_ft8.cpp中。
* <p>
* -----2022.5.9-----
* 如果系统没有发射信号,触发器会在每一个周期触发录音动作,因录音开始和结束要浪费一些时间,如果不干预上一个录音的动作,将出现
* 连续的周期内录音动作重叠,造成第二个录音动作失败。所以,第二个周期的录音开始前,要停止前一个周期的录音,造成的结果就是每一次录音
* 的开始时间要晚于周期开始300毫秒模拟器的结果实际录音的长度一般在14.77秒左右
* <p>
* @author BG7YOZ
* @date 2022.5.6
*/
import static com.bg7yoz.ft8cn.GeneralVariables.getStringFromResource;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.media.AudioManager;
import android.os.Handler;
import android.util.Log;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;
import com.bg7yoz.ft8cn.callsign.CallsignDatabase;
import com.bg7yoz.ft8cn.callsign.CallsignInfo;
import com.bg7yoz.ft8cn.callsign.OnAfterQueryCallsignLocation;
import com.bg7yoz.ft8cn.connector.BluetoothRigConnector;
import com.bg7yoz.ft8cn.connector.CableConnector;
import com.bg7yoz.ft8cn.connector.CableSerialPort;
import com.bg7yoz.ft8cn.connector.ConnectMode;
import com.bg7yoz.ft8cn.connector.FlexConnector;
import com.bg7yoz.ft8cn.connector.IComWifiConnector;
import com.bg7yoz.ft8cn.database.ControlMode;
import com.bg7yoz.ft8cn.database.DatabaseOpr;
import com.bg7yoz.ft8cn.database.OnAfterQueryFollowCallsigns;
import com.bg7yoz.ft8cn.database.OperationBand;
import com.bg7yoz.ft8cn.flex.FlexRadio;
import com.bg7yoz.ft8cn.ft8listener.FT8SignalListener;
import com.bg7yoz.ft8cn.ft8listener.OnFt8Listen;
import com.bg7yoz.ft8cn.ft8transmit.FT8TransmitSignal;
import com.bg7yoz.ft8cn.ft8transmit.OnDoTransmitted;
import com.bg7yoz.ft8cn.ft8transmit.OnTransmitSuccess;
import com.bg7yoz.ft8cn.html.LogHttpServer;
import com.bg7yoz.ft8cn.icom.IComWifiRig;
import com.bg7yoz.ft8cn.log.QSLCallsignRecord;
import com.bg7yoz.ft8cn.log.QSLRecord;
import com.bg7yoz.ft8cn.log.SWLQsoList;
import com.bg7yoz.ft8cn.rigs.BaseRig;
import com.bg7yoz.ft8cn.rigs.BaseRigOperation;
import com.bg7yoz.ft8cn.rigs.ElecraftRig;
import com.bg7yoz.ft8cn.rigs.Flex6000Rig;
import com.bg7yoz.ft8cn.rigs.FlexNetworkRig;
import com.bg7yoz.ft8cn.rigs.GuoHeQ900Rig;
import com.bg7yoz.ft8cn.rigs.IcomRig;
import com.bg7yoz.ft8cn.rigs.InstructionSet;
import com.bg7yoz.ft8cn.rigs.KenwoodKT90Rig;
import com.bg7yoz.ft8cn.rigs.KenwoodTS590Rig;
import com.bg7yoz.ft8cn.rigs.OnRigStateChanged;
import com.bg7yoz.ft8cn.rigs.XieGu6100Rig;
import com.bg7yoz.ft8cn.rigs.XieGuRig;
import com.bg7yoz.ft8cn.rigs.Yaesu2Rig;
import com.bg7yoz.ft8cn.rigs.Yaesu38Rig;
import com.bg7yoz.ft8cn.rigs.Yaesu38_450Rig;
import com.bg7yoz.ft8cn.rigs.Yaesu39Rig;
import com.bg7yoz.ft8cn.rigs.YaesuDX10Rig;
import com.bg7yoz.ft8cn.spectrum.SpectrumListener;
import com.bg7yoz.ft8cn.timer.OnUtcTimer;
import com.bg7yoz.ft8cn.timer.UtcTimer;
import com.bg7yoz.ft8cn.ui.ToastMessage;
import com.bg7yoz.ft8cn.wave.HamRecorder;
import com.bg7yoz.ft8cn.wave.OnGetVoiceDataDone;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainViewModel extends ViewModel {
String TAG = "ft8cn MainViewModel";
public boolean configIsLoaded=false;
private static MainViewModel viewModel = null;//当前存在的实例。
//public static Application application;
//public int decoded_counter = 0;//解码的总条数
public final ArrayList<Ft8Message> ft8Messages = new ArrayList<>();//消息列表
public UtcTimer utcTimer;//同步触发动作的计时器。
//public boolean showTrackerInfo=true;
//public CallsignDatabase callsignDatabase = null;//呼号信息的数据库
public DatabaseOpr databaseOpr;//配置信息,和相关数据的数据库
public MutableLiveData<Integer> mutable_Decoded_Counter = new MutableLiveData<>();//解码的总条数
public int currentDecodeCount = 0;//本次解码的条数
public MutableLiveData<ArrayList<Ft8Message>> mutableFt8MessageList = new MutableLiveData<>();//消息列表
public MutableLiveData<Long> timerSec = new MutableLiveData<>();//当前UTC时间。更新频率由UtcTimer确定未触发时约100毫秒。
public MutableLiveData<Boolean> mutableIsRecording = new MutableLiveData<>();//是否处于录音状态
public MutableLiveData<Boolean> mutableHamRecordIsRunning = new MutableLiveData<>();//HamRecord是否运转
public MutableLiveData<Float> mutableTimerOffset = new MutableLiveData<>();//本周期的时间延迟
public MutableLiveData<Boolean> mutableIsDecoding = new MutableLiveData<>();//会触发频谱图中的标记动作
public ArrayList<Ft8Message> currentMessages = null;//本周期解码的消息(用于画到频谱上)
public MutableLiveData<Boolean> mutableIsFlexRadio=new MutableLiveData<>();//是不是flex电台
private final ExecutorService getQTHThreadPool = Executors.newCachedThreadPool();
private final ExecutorService sendWaveDataThreadPool = Executors.newCachedThreadPool();
private final GetQTHRunnable getQTHRunnable=new GetQTHRunnable(this);
private final SendWaveDataRunnable sendWaveDataRunnable=new SendWaveDataRunnable();
public HamRecorder hamRecorder;//用于录音的对象
public FT8SignalListener ft8SignalListener;//用于监听FT8信号并解码的对象
public FT8TransmitSignal ft8TransmitSignal;//用于发射信号用的对象
public SpectrumListener spectrumListener;//用于画频谱的对象
public boolean markMessage = true;//是否标记消息开关
//控制电台的方式
public OperationBand operationBand = null;
private SWLQsoList swlQsoList=new SWLQsoList();//用于记录SWL的QSO对象对SWL QSO做判断防止重复。
public MutableLiveData<ArrayList<CableSerialPort.SerialPort>> mutableSerialPorts = new MutableLiveData<>();
private ArrayList<CableSerialPort.SerialPort> serialPorts;//串口列表
public BaseRig baseRig;//电台
private final OnRigStateChanged onRigStateChanged = new OnRigStateChanged() {
@Override
public void onDisconnected() {
//与电台连接中断
ToastMessage.show(getStringFromResource(R.string.disconnect_rig));
}
@Override
public void onConnected() {
//与电台建立连接
ToastMessage.show(getStringFromResource(R.string.connected_rig));
}
@Override
public void onPttChanged(boolean isOn) {
}
@Override
public void onFreqChanged(long freq) {
//当前频率:%s
ToastMessage.show(String.format(getStringFromResource(R.string.current_frequency)
, BaseRigOperation.getFrequencyAllInfo(freq)));
//把频率的变化写回到全局变量中
GeneralVariables.band = freq;
GeneralVariables.bandListIndex = OperationBand.getIndexByFreq(freq);
GeneralVariables.mutableBandChange.postValue(GeneralVariables.bandListIndex);
databaseOpr.getAllQSLCallsigns();//通联成功的呼号读出来
}
@Override
public void onRunError(String message) {
//与电台通讯出现错误,
ToastMessage.show(String.format(getStringFromResource(R.string.radio_communication_error)
, message));
}
};
//发射信号用的消息列表
//public ArrayList<Ft8Message> transmitMessages = new ArrayList<>();
//public MutableLiveData<ArrayList<Ft8Message>> mutableTransmitMessages = new MutableLiveData<>();
public MutableLiveData<Integer> mutableTransmitMessagesCount=new MutableLiveData<>();
public boolean deNoise = false;//在频谱中抑制噪声
//*********日志查询需要的变量********************
public boolean logListShowCallsign = false;//在日志查询列表的表现形式
public String queryKey = "";//查询的关键字
public int queryFilter = 0;//过滤0全部1确认2未确认
public MutableLiveData<Integer> mutableQueryFilter = new MutableLiveData<>();
public ArrayList<QSLCallsignRecord> callsignRecords=new ArrayList<>();
//public ArrayList<QSLRecordStr> qslRecords=new ArrayList<>();
//********************************************
//关注呼号的列表
//public ArrayList<String> followCallsign = new ArrayList<>();
//日志管理HTTP SERVER
private final LogHttpServer httpServer;
/**
* 获取MainViewModel的实例确保存在唯一的MainViewModel实例该实例在APP的全部生存周期中。
*
* @param owner ViewModelStoreOwner 所有者一般为Activity或Fragment。
* @return MainViewModel 返回一个MainViewModel实例
*/
public static MainViewModel getInstance(ViewModelStoreOwner owner) {
if (viewModel == null) {
viewModel = new ViewModelProvider(owner).get(MainViewModel.class);
}
return viewModel;
}
/**
* 获取消息列表中指定的消息
*
* @param position 在Mutable类型的列表中的位置
* @return 返回一个Ft8Message类型的解码后的信息
*/
public Ft8Message getFt8Message(int position) {
return Objects.requireNonNull(ft8Messages.get(position));
}
/**
* MainViewModel的构造函数主要完成一下事情
* 1.创建与UTC同步的时钟时钟是UtcTimer类内核是用Timer和TimerTask实现的。回调函数是多线程的要考虑线程安全的问题。
* 2.创建Mutable型的解码消息列表。
*/
//@RequiresApi(api = Build.VERSION_CODES.N)
public MainViewModel() {
//获取配置信息。
databaseOpr = DatabaseOpr.getInstance(GeneralVariables.getMainContext()
, "data.db");
mutableIsDecoding.postValue(false);//解码状态
//创录音对象
hamRecorder = new HamRecorder(null);
hamRecorder.startRecord();
mutableIsFlexRadio.setValue(false);
//创建用于显示时间的计时器
utcTimer = new UtcTimer(10, false, new OnUtcTimer() {
@Override
public void doHeartBeatTimer(long utc) {//不触发时的时钟信息
}
@Override
public void doOnSecTimer(long utc) {//当指定间隔时触发时
timerSec.postValue(utc);//发送当前UTC时间
mutableIsRecording.postValue(hamRecorder.isRunning());
mutableHamRecordIsRunning.postValue(hamRecorder.isRunning());//发送当前计时器状态
}
});
utcTimer.start();//启动计时器
//同步一下时间。microsoft的NTP服务器
UtcTimer.syncTime(null);
mutableFt8MessageList.setValue(ft8Messages);
//创建监听对象,回调中的动作用于处理解码、发射、关注的呼号列表添加等操作
ft8SignalListener = new FT8SignalListener(databaseOpr, new OnFt8Listen() {
@Override
public void beforeListen(long utc) {
mutableIsDecoding.postValue(true);
}
@Override
public void afterDecode(long utc, float time_sec, int sequential, ArrayList<Ft8Message> messages) {
synchronized (ft8Messages) {
ft8Messages.addAll(messages);//添加消息到列表
}
GeneralVariables.deleteArrayListMore(ft8Messages);//删除多余的消息,FT8CN限定的可展示消息的总数量
mutableFt8MessageList.postValue(ft8Messages);//触发添加消息的动作,让界面能观察到
mutableTimerOffset.postValue(time_sec);//本次时间偏移量
findIncludedCallsigns(messages);//查找符合条件的消息,放到呼叫列表中
//检查发射程序。从消息列表中解析发射的程序
ft8TransmitSignal.parseMessageToFunction(messages);
mutableIsDecoding.postValue(false);//解码的状态,会触发频谱图中的标记动作
currentMessages = messages;//保存本次解码的消息
getQTHRunnable.messages=messages;
getQTHThreadPool.execute(getQTHRunnable);//用线程池的方式查询归属地
if (GeneralVariables.saveSWLMessage) {
databaseOpr.writeMessage(messages);//把SWL消息写到数据库
}
//检查QSO of SWL,并保存到SWLQSOTable中的通联列表qsoList中
if (GeneralVariables.saveSWL_QSO){
swlQsoList.findSwlQso(messages, ft8Messages, new SWLQsoList.OnFoundSwlQso() {
@Override
public void doFound(QSLRecord record) {
databaseOpr.addSWL_QSO(record);//把SWL QSO保存到数据库
ToastMessage.show(record.swlQSOInfo());
}
});
}
//从列表中查找呼号和网格对应关系,并添加到表中
getCallsignAndGrid(messages);
}
});
ft8SignalListener.setOnWaveDataListener(new FT8SignalListener.OnWaveDataListener() {
@Override
public void getVoiceData(int duration, boolean afterDoneRemove, OnGetVoiceDataDone getVoiceDataDone) {
hamRecorder.getVoiceData(duration, afterDoneRemove, getVoiceDataDone);
}
});
ft8SignalListener.startListen();
//频谱监听对象
spectrumListener = new SpectrumListener(hamRecorder);
//创建发射对象回调发射前发射后、QSL成功后。
ft8TransmitSignal = new FT8TransmitSignal(databaseOpr, new OnDoTransmitted() {
@Override
public void onBeforeTransmit(Ft8Message message, int functionOder) {
if (GeneralVariables.controlMode == ControlMode.CAT
|| GeneralVariables.controlMode == ControlMode.RTS
|| GeneralVariables.controlMode == ControlMode.DTR) {
if (baseRig != null) {
if (GeneralVariables.connectMode != ConnectMode.NETWORK) stopSco();
baseRig.setPTT(true);
}
}
if (ft8TransmitSignal.isActivated()) {
GeneralVariables.transmitMessages.add(message);
//mutableTransmitMessages.postValue(GeneralVariables.transmitMessages);
mutableTransmitMessagesCount.postValue(1);
}
}
@Override
public void onAfterTransmit(Ft8Message message, int functionOder) {
if (GeneralVariables.controlMode == ControlMode.CAT
|| GeneralVariables.controlMode == ControlMode.RTS
|| GeneralVariables.controlMode == ControlMode.DTR) {
if (baseRig != null) {
baseRig.setPTT(false);
if (GeneralVariables.connectMode != ConnectMode.NETWORK) startSco();
}
}
}
@Override
public void onAfterGenerate(float[] data) {
if (GeneralVariables.connectMode == ConnectMode.NETWORK) {
if (baseRig != null) {
if (baseRig.isConnected()) {
sendWaveDataRunnable.baseRig=baseRig;
sendWaveDataRunnable.data=data;
//以线程池的方式执行网络数据包发送
sendWaveDataThreadPool.execute(sendWaveDataRunnable);
}
}
}
}
}, new OnTransmitSuccess() {//当通联成功时
@Override
public void doAfterTransmit(QSLRecord qslRecord) {
databaseOpr.addQSL_Callsign(qslRecord);//两个操作把呼号和QSL记录下来
if (qslRecord.getToCallsign() != null) {//把通联成功的分区加入到分区列表
GeneralVariables.callsignDatabase.getCallsignInformation(qslRecord.getToCallsign()
, new OnAfterQueryCallsignLocation() {
@Override
public void doOnAfterQueryCallsignLocation(CallsignInfo callsignInfo) {
GeneralVariables.addDxcc(callsignInfo.DXCC);
GeneralVariables.addItuZone(callsignInfo.ITUZone);
GeneralVariables.addCqZone(callsignInfo.CQZone);
}
});
}
}
});
//打开HTTP SERVER
httpServer = new LogHttpServer(this, LogHttpServer.DEFAULT_PORT);
try {
httpServer.start();
} catch (IOException e) {
Log.e(TAG, "http server error:" + e.getMessage());
}
}
public void setTransmitIsFreeText(boolean isFreeText){
if (ft8TransmitSignal!=null) {
ft8TransmitSignal.setTransmitFreeText(isFreeText);
}
}
public boolean getTransitIsFreeText(){
if (ft8TransmitSignal!=null){
return ft8TransmitSignal.isTransmitFreeText();
}
return false;
}
/**
* 查找符合条件的消息,放到呼叫列表中
*
* @param messages 消息
*/
private void findIncludedCallsigns(ArrayList<Ft8Message> messages) {
Log.d(TAG, "findIncludedCallsigns: 查找关注的呼号");
if (ft8TransmitSignal.isActivated() && ft8TransmitSignal.sequential != UtcTimer.getNowSequential()) {
return;
}
int count=0;
for (Ft8Message msg : messages) {
//与我的呼号有关,与关注的呼号有关
if (msg.getCallsignFrom().equals(GeneralVariables.myCallsign)
|| msg.getCallsignTo().equals(GeneralVariables.myCallsign)
|| GeneralVariables.callsignInFollow(msg.getCallsignFrom())
|| (GeneralVariables.callsignInFollow(msg.getCallsignTo()) && (msg.getCallsignTo() != null))
|| (GeneralVariables.autoFollowCQ && msg.checkIsCQ())) {//是CQ并且允许关注CQ
//看不是通联成功的呼号的消息
msg.isQSL_Callsign = GeneralVariables.checkQSLCallsign(msg.getCallsignFrom());
if (!GeneralVariables.checkIsExcludeCallsign(msg.callsignFrom)) {//不在排除呼号前缀的,才加入列表
count++;
GeneralVariables.transmitMessages.add(msg);
}
}
}
GeneralVariables.deleteArrayListMore(GeneralVariables.transmitMessages);//删除多余的消息
//mutableTransmitMessages.postValue(GeneralVariables.transmitMessages);
mutableTransmitMessagesCount.postValue(count);
}
/**
* 清除传输消息列表
*/
public void clearTransmittingMessage() {
GeneralVariables.transmitMessages.clear();
mutableTransmitMessagesCount.postValue(0);
}
/**
* 从消息列表中查找呼号和网格的对应关系
*
* @param messages 消息列表
*/
private void getCallsignAndGrid(ArrayList<Ft8Message> messages) {
for (Ft8Message msg : messages) {
if (GeneralVariables.checkFun1(msg.extraInfo)) {//检查是不是网格
//如果内存表中没有,或不一致,就写入数据库中
if (!GeneralVariables.getCallsignHasGrid(msg.getCallsignFrom(), msg.maidenGrid)) {
databaseOpr.addCallsignQTH(msg.getCallsignFrom(), msg.maidenGrid);//写数据库
}
GeneralVariables.addCallsignAndGrid(msg.getCallsignFrom(), msg.maidenGrid);
}
}
}
/**
* 清除消息列表
*/
public void clearFt8MessageList() {
ft8Messages.clear();
mutable_Decoded_Counter.postValue(ft8Messages.size());
mutableFt8MessageList.postValue(ft8Messages);
}
/**
* 删除单个文件
*
* @param fileName 要删除的文件的文件名
*/
public static void deleteFile(String fileName) {
File file = new File(fileName);
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
file.delete();
}
}
/**
* 向关注的呼号列表添加呼号
*
* @param callsign 呼号
*/
public void addFollowCallsign(String callsign) {
if (!GeneralVariables.followCallsign.contains(callsign)) {
GeneralVariables.followCallsign.add(callsign);
databaseOpr.addFollowCallsign(callsign);
}
}
/**
* 从数据库中获取关注的呼号列表
*/
public void getFollowCallsignsFromDataBase() {
databaseOpr.getFollowCallsigns(new OnAfterQueryFollowCallsigns() {
@Override
public void doOnAfterQueryFollowCallsigns(ArrayList<String> callsigns) {
for (String s : callsigns) {
if (!GeneralVariables.followCallsign.contains(s)) {
GeneralVariables.followCallsign.add(s);
}
}
}
});
}
/**
* 设置操作载波频率。如果电台没有连接,就有操作
*/
public void setOperationBand() {
if (!isRigConnected()) {
return;
}
//先设置上边带,再设置频率
baseRig.setUsbModeToRig();//设置上边带
//此处延迟1秒发送第二个指令是防止协谷X6100断开连接的问题
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
baseRig.setFreq(GeneralVariables.band);//设置频率
baseRig.setFreqToRig();
}
}, 800);
}
public void setCivAddress() {
if (baseRig != null) {
baseRig.setCivAddress(GeneralVariables.civAddress);
}
}
public void setControlMode() {
if (baseRig != null) {
baseRig.setControlMode(GeneralVariables.controlMode);
}
}
/**
* 通过USB连接电台
*
* @param context context
* @param port 串口
*/
public void connectCableRig(Context context, CableSerialPort.SerialPort port) {
if (GeneralVariables.controlMode == ControlMode.VOX) {//如果当前是VOX就改成CAT模式
GeneralVariables.controlMode = ControlMode.CAT;
}
connectRig();
if (baseRig == null) {
return;
}
baseRig.setControlMode(GeneralVariables.controlMode);
CableConnector connector = new CableConnector(context, port, GeneralVariables.baudRate
, GeneralVariables.controlMode);
baseRig.setOnRigStateChanged(onRigStateChanged);
baseRig.setConnector(connector);
connector.connect();
//晚1秒钟设置模式防止有的电台反应不过来
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
setOperationBand();//设置载波频率
}
}, 1000);
}
public void connectBluetoothRig(Context context, BluetoothDevice device) {
GeneralVariables.controlMode = ControlMode.CAT;//蓝牙控制模式只能是CAT控制
connectRig();
if (baseRig == null) {
return;
}
baseRig.setControlMode(GeneralVariables.controlMode);
BluetoothRigConnector connector = BluetoothRigConnector.getInstance(context, device.getAddress()
, GeneralVariables.controlMode);
baseRig.setOnRigStateChanged(onRigStateChanged);
baseRig.setConnector(connector);
new Handler().postDelayed(new Runnable() {//蓝牙连接是需要时间的等2秒再设置频率
@Override
public void run() {
setOperationBand();//设置载波频率
}
}, 5000);
}
public void connectIComWifiRig(Context context, IComWifiRig iComWifiRig) {
if (GeneralVariables.connectMode == ConnectMode.NETWORK) {
if (baseRig != null) {
if (baseRig.getConnector() != null) {
baseRig.getConnector().disconnect();
}
}
}
GeneralVariables.controlMode = ControlMode.CAT;//网络控制模式
IComWifiConnector iComWifiConnector = new IComWifiConnector(GeneralVariables.controlMode
, iComWifiRig);
iComWifiConnector.setOnWifiDataReceived(new IComWifiConnector.OnWifiDataReceived() {
@Override
public void OnWaveReceived(int bufferLen, float[] buffer) {
hamRecorder.doOnWaveDataReceived(bufferLen, buffer);
}
@Override
public void OnCivReceived(byte[] data) {
}
});
iComWifiConnector.connect();
connectRig();
baseRig.setControlMode(GeneralVariables.controlMode);
baseRig.setOnRigStateChanged(onRigStateChanged);
baseRig.setConnector(iComWifiConnector);
//
new Handler().postDelayed(new Runnable() {//蓝牙连接是需要时间的等2秒再设置频率
@Override
public void run() {
setOperationBand();//设置载波频率
}
}, 1000);
}
/**
* 连接到flexRadio
*
* @param context context
* @param flexRadio flexRadio对象
*/
public void connectFlexRadioRig(Context context, FlexRadio flexRadio) {
if (GeneralVariables.connectMode == ConnectMode.NETWORK) {
if (baseRig != null) {
if (baseRig.getConnector() != null) {
baseRig.getConnector().disconnect();
}
}
}
GeneralVariables.controlMode = ControlMode.CAT;//网络控制模式
FlexConnector flexConnector = new FlexConnector(context, flexRadio, GeneralVariables.controlMode);
flexConnector.setOnWaveDataReceived(new FlexConnector.OnWaveDataReceived() {
@Override
public void OnDataReceived(int bufferLen, float[] buffer) {
hamRecorder.doOnWaveDataReceived(bufferLen, buffer);
}
});
flexConnector.connect();
connectRig();
baseRig.setOnRigStateChanged(onRigStateChanged);
baseRig.setConnector(flexConnector);
//
new Handler().postDelayed(new Runnable() {//连接是需要时间的等2秒再设置频率
@Override
public void run() {
setOperationBand();//设置载波频率
}
}, 3000);
}
/**
* 根据指令集创建不同型号的电台
*/
private void connectRig() {
if ((GeneralVariables.instructionSet == InstructionSet.FLEX_NETWORK)
|| (GeneralVariables.instructionSet == InstructionSet.ICOM
&& GeneralVariables.connectMode == ConnectMode.NETWORK)) {
hamRecorder.setDataFromLan();
} else {
hamRecorder.setDataFromMic();
}
baseRig = null;
//此处判断是用什么类型的电台ICOM,YAESU 2,YAESU 3
switch (GeneralVariables.instructionSet) {
case InstructionSet.ICOM:
baseRig = new IcomRig(GeneralVariables.civAddress);
break;
case InstructionSet.YAESU_2:
baseRig = new Yaesu2Rig();
break;
case InstructionSet.YAESU_3_9:
baseRig = new Yaesu39Rig();//yaesu3代指令9位频率
break;
case InstructionSet.YAESU_3_8:
baseRig = new Yaesu38Rig();//yaesu3代指令8位频率
break;
case InstructionSet.YAESU_3_450:
baseRig = new Yaesu38_450Rig();//yaesu3代指令8位频率
break;
case InstructionSet.KENWOOD_TK90:
baseRig = new KenwoodKT90Rig();//建伍TK90
break;
case InstructionSet.YAESU_DX10:
baseRig = new YaesuDX10Rig();//YAESU DX10 DX101
break;
case InstructionSet.KENWOOD_TS590:
baseRig = new KenwoodTS590Rig();//KENWOOD TS590
break;
case InstructionSet.GUOHE_Q900:
baseRig = new GuoHeQ900Rig();//国赫Q900
break;
case InstructionSet.XIEGUG90S://协谷USB模式
baseRig = new XieGuRig(GeneralVariables.civAddress);//协谷G90S
break;
case InstructionSet.ELECRAFT:
baseRig = new ElecraftRig();//ELECRAFT
break;
case InstructionSet.FLEX_CABLE:
baseRig = new Flex6000Rig();//FLEX6000
break;
case InstructionSet.FLEX_NETWORK:
baseRig = new FlexNetworkRig();
break;
case InstructionSet.XIEGU_6100:
baseRig = new XieGu6100Rig(GeneralVariables.civAddress);//协谷6100
break;
}
mutableIsFlexRadio.postValue(GeneralVariables.instructionSet==InstructionSet.FLEX_NETWORK);
}
/**
* 检察电台是否处于连接状态,两种情况rigBaseClass没建立串口没连接成功
*
* @return 是否连接
*/
public boolean isRigConnected() {
if (baseRig == null) {
return false;
} else {
return baseRig.isConnected();
}
}
/**
* 获取串口设备列表
*/
public void getUsbDevice() {
serialPorts =
CableSerialPort.listSerialPorts(GeneralVariables.getMainContext());
mutableSerialPorts.postValue(serialPorts);
}
public void startSco() {
AudioManager audioManager = (AudioManager) GeneralVariables.getMainContext()
.getSystemService(Context.AUDIO_SERVICE);
if (audioManager == null) return;
if (!audioManager.isBluetoothScoAvailableOffCall()) {
//蓝牙设备不支持录音
ToastMessage.show(getStringFromResource(R.string.does_not_support_recording));
return;
}
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();//71毫秒
audioManager.setSpeakerphoneOn(false);//进入耳机模式
}
public void stopSco() {
AudioManager audioManager = (AudioManager) GeneralVariables.getMainContext()
.getSystemService(Context.AUDIO_SERVICE);
if (audioManager == null) return;
if (audioManager.isBluetoothScoOn()) {
audioManager.setBluetoothScoOn(false);
audioManager.stopBluetoothSco();
audioManager.setSpeakerphoneOn(true);//退出耳机模式
}
}
public void setBlueToothOn() {
AudioManager audioManager = (AudioManager) GeneralVariables.getMainContext()
.getSystemService(Context.AUDIO_SERVICE);
if (audioManager == null) return;
if (!audioManager.isBluetoothScoAvailableOffCall()) {
//蓝牙设备不支持录音
ToastMessage.show(getStringFromResource(R.string.does_not_support_recording));
}
/*
播放音乐的对应的就是MODE_NORMAL, 如果使用外放播则调用audioManager.setSpeakerphoneOn(true)即可.
若使用耳机和听筒,则需要先设置模式为MODE_IN_CALL(3.0以前)或MODE_IN_COMMUNICATION(3.0以后).
*/
audioManager.setMode(AudioManager.MODE_NORMAL);//178毫秒
audioManager.setBluetoothScoOn(true);
audioManager.stopBluetoothSco();
audioManager.startBluetoothSco();//71毫秒
audioManager.setSpeakerphoneOn(false);//进入耳机模式
//进入到蓝牙耳机模式
ToastMessage.show(getStringFromResource(R.string.bluetooth_headset_mode));
}
public void setBlueToothOff() {
AudioManager audioManager = (AudioManager) GeneralVariables.getMainContext()
.getSystemService(Context.AUDIO_SERVICE);
if (audioManager == null) return;
if (audioManager.isBluetoothScoOn()) {
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setBluetoothScoOn(false);
audioManager.stopBluetoothSco();
audioManager.setSpeakerphoneOn(true);//退出耳机模式
}
//离开蓝牙耳机模式
ToastMessage.show(getStringFromResource(R.string.bluetooth_Headset_mode_cancelled));
}
/**
* 查询蓝牙是否连接
*
* @return 是否
*/
@SuppressLint("MissingPermission")
public boolean isBTConnected() {
BluetoothAdapter blueAdapter = BluetoothAdapter.getDefaultAdapter();
if (blueAdapter == null) return false;
//蓝牙头戴式耳机,支持语音输入输出
int headset = blueAdapter.getProfileConnectionState(BluetoothProfile.HEADSET);
int a2dp = blueAdapter.getProfileConnectionState(BluetoothProfile.A2DP);
return headset == BluetoothAdapter.STATE_CONNECTED || a2dp == BluetoothAdapter.STATE_CONNECTED;
}
private static class GetQTHRunnable implements Runnable {
MainViewModel mainViewModel;
ArrayList<Ft8Message> messages;
public GetQTHRunnable(MainViewModel mainViewModel) {
this.mainViewModel=mainViewModel;
}
@Override
public void run() {
CallsignDatabase.getMessagesLocation(
GeneralVariables.callsignDatabase.getDb(), messages);
mainViewModel.currentDecodeCount = messages.size();
//此变量也是告诉消息列表变化的
mainViewModel.mutable_Decoded_Counter.postValue(
mainViewModel.currentDecodeCount);//告知界面消息的总数量
}
}
private static class SendWaveDataRunnable implements Runnable{
BaseRig baseRig;
float[] data;
@Override
public void run() {
if (baseRig!=null&&data!=null){
baseRig.sendWaveData(data);//实际生成的数据是12.64+0.04,0.04是生成的0数据
}
}
}
}