2023-08-15 05:18:25 +00:00
|
|
|
|
package com.bg7yoz.ft8cn.flex;
|
|
|
|
|
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
|
|
import java.net.DatagramPacket;
|
|
|
|
|
import java.net.DatagramSocket;
|
|
|
|
|
import java.net.SocketException;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Timer;
|
|
|
|
|
import java.util.TimerTask;
|
|
|
|
|
|
|
|
|
|
// VITA 形成的发现消息解析器的枚举定义
|
2024-01-24 07:09:36 +00:00
|
|
|
|
//enum VitaTokens {
|
|
|
|
|
// nullToken ,
|
|
|
|
|
// ipToken,
|
|
|
|
|
// portToken,
|
|
|
|
|
// modelToken,
|
|
|
|
|
// serialToken,
|
|
|
|
|
// callsignToken,
|
|
|
|
|
// nameToken,
|
|
|
|
|
// dpVersionToken,
|
|
|
|
|
// versionToken,
|
|
|
|
|
// statusToken,
|
|
|
|
|
//};
|
2023-08-15 05:18:25 +00:00
|
|
|
|
/**
|
|
|
|
|
* RadioFactory 当前发现的所有收音机。
|
|
|
|
|
* RadioFactory: 实例化这个类来创建一个 Radio Factory,它将为网络上发现的无线电维护FlexRadio列表flexRadios。
|
|
|
|
|
*
|
|
|
|
|
* 通过Upd协议,在4992端口的广播数据中获取vita协议数据,并解析出序列号,用于更新电台列表flexRadios。
|
|
|
|
|
* @author BGY70Z
|
|
|
|
|
* @date 2023-03-20
|
|
|
|
|
*/
|
|
|
|
|
public class FlexRadioFactory {
|
|
|
|
|
private static final String TAG="FlexRadioFactory";
|
|
|
|
|
private static final int FLEX_DISCOVERY_PORT =4992;
|
|
|
|
|
private static FlexRadioFactory instance=null;
|
|
|
|
|
private final RadioUdpClient broadcastClient ;
|
|
|
|
|
private OnFlexRadioEvents onFlexRadioEvents;
|
|
|
|
|
|
|
|
|
|
private Timer refreshTimer=null;
|
|
|
|
|
private TimerTask refreshTask=null;
|
|
|
|
|
|
|
|
|
|
public ArrayList<FlexRadio> flexRadios=new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取电台列表实例
|
|
|
|
|
* @return 电台列表实例
|
|
|
|
|
*/
|
|
|
|
|
public static FlexRadioFactory getInstance(){
|
|
|
|
|
if (instance==null){
|
|
|
|
|
instance= new FlexRadioFactory();
|
|
|
|
|
}
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public FlexRadioFactory() {
|
|
|
|
|
broadcastClient = new RadioUdpClient(FLEX_DISCOVERY_PORT);
|
|
|
|
|
|
|
|
|
|
broadcastClient.setOnUdpEvents(new RadioUdpClient.OnUdpEvents() {
|
|
|
|
|
@Override
|
|
|
|
|
public void OnReceiveData(DatagramSocket socket, DatagramPacket packet, byte[] data) {
|
|
|
|
|
VITA vita = new VITA(data);
|
|
|
|
|
if (vita.isAvailable//如果数据包有效,且classId=0x534CFFFF,StreamId=0x800,更新电台列表
|
|
|
|
|
&&vita.informationClassCode==VITA.FLEX_CLASS_ID
|
|
|
|
|
&&vita.packetClassCode==VITA.VS_Discovery
|
|
|
|
|
&&vita.streamId==VITA.FLEX_Discovery_stream_ID){
|
|
|
|
|
updateFlexRadioList(new String(vita.payload));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
try {
|
|
|
|
|
broadcastClient.setActivated(true);
|
|
|
|
|
} catch (SocketException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
Log.e(TAG, "FlexRadioFactory: "+e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void startRefreshTimer(){
|
|
|
|
|
if (refreshTimer==null) {
|
|
|
|
|
refreshTask=new TimerTask() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
Log.e(TAG, "run: 检查离线" );
|
|
|
|
|
checkOffLineRadios();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
refreshTimer=new Timer();
|
|
|
|
|
refreshTimer.schedule(refreshTask, 1000, 1000);//检查电台列表中的电台是否在线(每一秒)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void cancelRefreshTimer(){
|
|
|
|
|
if (refreshTimer!=null){
|
|
|
|
|
refreshTimer.cancel();
|
|
|
|
|
refreshTimer=null;
|
|
|
|
|
refreshTask.cancel();
|
|
|
|
|
refreshTask=null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从数据中查找电台的序列号
|
|
|
|
|
* @param s 数据
|
|
|
|
|
* @return 序列号
|
|
|
|
|
*/
|
|
|
|
|
private String getSerialNum(String s){
|
|
|
|
|
String[] strings=s.split(" ");
|
|
|
|
|
for (int i = 0; i <strings.length ; i++) {
|
|
|
|
|
if (strings[i].toLowerCase().startsWith("serial")){
|
|
|
|
|
return strings[i].substring("serial".length()+1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 在电台列表中查找有没有指定序列号的电台
|
|
|
|
|
* @param serial 序列号
|
|
|
|
|
* @return 电台实例
|
|
|
|
|
*/
|
|
|
|
|
public FlexRadio checkFlexRadioBySerial(String serial){
|
|
|
|
|
for (FlexRadio radio:flexRadios) {
|
|
|
|
|
if (radio.isEqual(serial)){
|
|
|
|
|
return radio;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private synchronized void updateFlexRadioList(String s){
|
|
|
|
|
String serial=getSerialNum(s);
|
|
|
|
|
if (serial.equals("")){return;}
|
|
|
|
|
FlexRadio radio=checkFlexRadioBySerial(serial);
|
|
|
|
|
if (radio!=null){
|
|
|
|
|
radio.updateLastSeen();
|
|
|
|
|
}else {
|
|
|
|
|
radio=new FlexRadio(s);
|
|
|
|
|
if (onFlexRadioEvents!=null){
|
|
|
|
|
onFlexRadioEvents.OnFlexRadioAdded(radio);
|
|
|
|
|
}
|
|
|
|
|
flexRadios.add(radio);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查电台是不是离线,如果离线,触发离线事件
|
|
|
|
|
*/
|
|
|
|
|
private void checkOffLineRadios(){
|
|
|
|
|
for (FlexRadio radio:flexRadios) {
|
|
|
|
|
if (radio.isInvalidNow()){
|
|
|
|
|
if (onFlexRadioEvents!=null){
|
|
|
|
|
onFlexRadioEvents.OnFlexRadioInvalid(radio);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//***********Getter****************
|
|
|
|
|
public RadioUdpClient getBroadcastClient() {
|
|
|
|
|
return broadcastClient;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public OnFlexRadioEvents getOnFlexRadioEvents() {
|
|
|
|
|
return onFlexRadioEvents;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setOnFlexRadioEvents(OnFlexRadioEvents onFlexRadioEvents) {
|
|
|
|
|
this.onFlexRadioEvents = onFlexRadioEvents;
|
|
|
|
|
}
|
|
|
|
|
//*********************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 电台列表变化的接口
|
|
|
|
|
*/
|
|
|
|
|
public static interface OnFlexRadioEvents{
|
|
|
|
|
void OnFlexRadioAdded(FlexRadio flexRadio);
|
|
|
|
|
void OnFlexRadioInvalid(FlexRadio flexRadio);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|