mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Resolves #165 - P25 decoding channel stops arbitrarily and never recovers.
Issue identified with Patch Group management and circular dependencies that can develop because of stale patch groups. Refactored all patch group management into a new PatchGroupManager. Patch groups are now automatically deleted if we don't receive any update messages within 5 seconds. The PatchGroupAlias was also updated to not roll-up attributes from subordinate patched group aliases when those aliases are also patch group aliases -- this eliminates the circular dependency chaining. Added IOverflowListener interface and updated Sources to support overflow listeners. Updated ChannelState to register as an overflow listener so that it can visually depict to the user when the channel enters/exits source overflow state. Added new color pattern for OVERFLOW with yellow text on red.
This commit is contained in:
@@ -538,6 +538,9 @@ public class ProcessingChain implements IChannelEventListener
|
||||
module.reset();
|
||||
}
|
||||
|
||||
//Setup the channel state to monitor source overflow conditions
|
||||
mSource.setOverflowListener(mChannelState);
|
||||
|
||||
/* Register with the source to receive sample data. Setup a
|
||||
* timer task to process the buffer queues 50 times a second
|
||||
* (every 20 ms) */
|
||||
@@ -606,6 +609,7 @@ public class ProcessingChain implements IChannelEventListener
|
||||
if(mSource != null)
|
||||
{
|
||||
mSource.stop();
|
||||
mSource.setOverflowListener(null);
|
||||
|
||||
switch(mSource.getSampleType())
|
||||
{
|
||||
|
||||
@@ -19,9 +19,7 @@ package module.decode.p25;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import alias.PatchGroupAlias;
|
||||
import alias.id.AliasIDType;
|
||||
import alias.id.talkgroup.TalkgroupID;
|
||||
import channel.metadata.AliasedStringAttributeMonitor;
|
||||
import channel.metadata.Attribute;
|
||||
import channel.metadata.AttributeChangeRequest;
|
||||
@@ -163,7 +161,6 @@ public class P25DecoderState extends DecoderState
|
||||
private Map<Integer,IdentifierUpdate> mBands = new HashMap<>();
|
||||
private Map<String,Long> mRegistrations = new HashMap<>();
|
||||
private Map<String,IAdjacentSite> mNeighborMap = new HashMap<>();
|
||||
private Map<String,List<String>> mPatchGroupMap = new HashMap<>();
|
||||
|
||||
private String mLastCommandEventID;
|
||||
private String mLastPageEventID;
|
||||
@@ -188,6 +185,7 @@ public class P25DecoderState extends DecoderState
|
||||
private P25CallEvent mCurrentCallEvent;
|
||||
private List<String> mCallDetectTalkgroups = new ArrayList<>();
|
||||
private Map<String,P25CallEvent> mChannelCallMap = new HashMap<>();
|
||||
private PatchGroupManager mPatchGroupManager;
|
||||
|
||||
public P25DecoderState(AliasList aliasList,
|
||||
ChannelType channelType,
|
||||
@@ -199,6 +197,7 @@ public class P25DecoderState extends DecoderState
|
||||
mModulation = modulation;
|
||||
mIgnoreDataCalls = ignoreDataCalls;
|
||||
|
||||
mPatchGroupManager = new PatchGroupManager(aliasList, getCallEventBroadcaster());
|
||||
mSiteAttributeMonitor = new AliasedStringAttributeMonitor(Attribute.NETWORK_ID_2,
|
||||
getAttributeChangeRequestListener(), getAliasList(), AliasIDType.SITE);
|
||||
mFromTalkgroupMonitor = new AliasedStringAttributeMonitor(Attribute.PRIMARY_ADDRESS_FROM,
|
||||
@@ -2719,6 +2718,9 @@ public class P25DecoderState extends DecoderState
|
||||
switch(((MotorolaTSBKMessage)tsbk).getMotorolaOpcode())
|
||||
{
|
||||
case PATCH_GROUP_CHANNEL_GRANT:
|
||||
//Cleanup patch groups - auto-expire any patch groups before we allocate a channel
|
||||
mPatchGroupManager.cleanupPatchGroups();
|
||||
|
||||
PatchGroupVoiceChannelGrant pgvcg = (PatchGroupVoiceChannelGrant)tsbk;
|
||||
|
||||
channel = pgvcg.getChannel();
|
||||
@@ -2754,6 +2756,9 @@ public class P25DecoderState extends DecoderState
|
||||
mChannelCallMap.get(channel)));
|
||||
break;
|
||||
case PATCH_GROUP_CHANNEL_GRANT_UPDATE:
|
||||
//Cleanup patch groups - auto-expire any patch groups before we allocate a channel
|
||||
mPatchGroupManager.cleanupPatchGroups();
|
||||
|
||||
PatchGroupVoiceChannelGrantUpdate gvcgu = (PatchGroupVoiceChannelGrantUpdate)tsbk;
|
||||
|
||||
channel = gvcgu.getChannel1();
|
||||
@@ -2784,35 +2789,11 @@ public class P25DecoderState extends DecoderState
|
||||
break;
|
||||
case PATCH_GROUP_ADD:
|
||||
PatchGroupAdd pga = (PatchGroupAdd)tsbk;
|
||||
|
||||
if(addPatchGroup(pga.getPatchGroupAddress(), pga.getPatchedTalkgroups()))
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("PATCH GROUP:").append(pga.getPatchGroupAddress());
|
||||
sb.append(" ").append(pga.getPatchedTalkgroups());
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEventType.PATCH_GROUP_ADD)
|
||||
.aliasList(getAliasList())
|
||||
.details(sb.toString())
|
||||
.build());
|
||||
}
|
||||
mPatchGroupManager.updatePatchGroup(pga.getPatchGroupAddress(), pga.getPatchedTalkgroups());
|
||||
break;
|
||||
case PATCH_GROUP_DELETE:
|
||||
PatchGroupDelete pgd = (PatchGroupDelete)tsbk;
|
||||
|
||||
if(removePatchGroup(pgd.getPatchGroupAddress(), pgd.getPatchedTalkgroups()))
|
||||
{
|
||||
StringBuilder sbpgd = new StringBuilder();
|
||||
|
||||
sbpgd.append("PATCH GROUP:").append(pgd.getPatchGroupAddress());
|
||||
sbpgd.append(" ").append(pgd.getPatchedTalkgroups());
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEventType.PATCH_GROUP_DELETE)
|
||||
.aliasList(getAliasList())
|
||||
.details(sbpgd.toString())
|
||||
.build());
|
||||
}
|
||||
mPatchGroupManager.removePatchGroup(pgd.getPatchGroupAddress());
|
||||
break;
|
||||
case CCH_PLANNED_SHUTDOWN:
|
||||
if(!mControlChannelShutdownLogged)
|
||||
@@ -2827,174 +2808,14 @@ public class P25DecoderState extends DecoderState
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new patch group or updates an existing patch group with the patched talkgroup entries.
|
||||
*
|
||||
* @param patchGroupID for the patch group
|
||||
* @param talkgroupsToAdd to include in the patch group
|
||||
* @return true if the patch group or the patch group map was updated
|
||||
*/
|
||||
private boolean addPatchGroup(String patchGroupID, List<String> talkgroupsToAdd)
|
||||
{
|
||||
boolean updated = false;
|
||||
|
||||
if(patchGroupID != null && !talkgroupsToAdd.isEmpty())
|
||||
{
|
||||
List<String> patchedTalkgroups = mPatchGroupMap.get(patchGroupID);
|
||||
|
||||
if(patchedTalkgroups == null)
|
||||
{
|
||||
patchedTalkgroups = new ArrayList<>();
|
||||
}
|
||||
|
||||
for(String talkgroupToAdd : talkgroupsToAdd)
|
||||
{
|
||||
//Exclude the patch group ID if it is included in the patched talkgroup list so that we don't have
|
||||
//an infinite loop situation
|
||||
if(talkgroupToAdd.equals(patchGroupID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!patchedTalkgroups.contains(talkgroupToAdd))
|
||||
{
|
||||
patchedTalkgroups.add(talkgroupToAdd);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(updated)
|
||||
{
|
||||
mPatchGroupMap.put(patchGroupID, patchedTalkgroups);
|
||||
updatePatchAlias(patchGroupID, patchedTalkgroups);
|
||||
}
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the patched talkgroups from the patch group and removes the patch group from the patch group map if
|
||||
* there are no more patched talkgroups in the patch group.
|
||||
*
|
||||
* @param patchGroupID for the patch group
|
||||
* @param talkgroupsToRemove to remove from the patch group
|
||||
* @return true if the patch group or the patch group map was updated
|
||||
*/
|
||||
private boolean removePatchGroup(String patchGroupID, List<String> talkgroupsToRemove)
|
||||
{
|
||||
boolean updated = false;
|
||||
|
||||
if(patchGroupID != null && !talkgroupsToRemove.isEmpty())
|
||||
{
|
||||
List<String> patchedTalkgroups = mPatchGroupMap.get(patchGroupID);
|
||||
|
||||
if(patchedTalkgroups != null)
|
||||
{
|
||||
for(String talkgroupToRemove : talkgroupsToRemove)
|
||||
{
|
||||
if(patchedTalkgroups.contains(talkgroupToRemove))
|
||||
{
|
||||
patchedTalkgroups.remove(talkgroupToRemove);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(patchedTalkgroups.isEmpty())
|
||||
{
|
||||
mPatchGroupMap.remove(patchGroupID);
|
||||
removePatchGroupAlias(patchGroupID);
|
||||
updated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
updatePatchAlias(patchGroupID, patchedTalkgroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds/updates a patch group alias to the alias list containing aliases for each of the patched talkgroups. If the
|
||||
* patch group alias already exists, any patched talkgroups will be removed from the existing patch group alias and
|
||||
* replaced with the aliases corresponding to the patched talkgroup aliases.
|
||||
*
|
||||
* @param patchGroupID for the patch group
|
||||
* @param patchedTalkgroups containing the talkgroup IDs for each of the patched talkgroups
|
||||
*/
|
||||
private void updatePatchAlias(String patchGroupID, List<String> patchedTalkgroups)
|
||||
{
|
||||
PatchGroupAlias patchGroupAlias = null;
|
||||
|
||||
//Check for an existing alias for the patch talkgroup - do not include wildcard aliases
|
||||
Alias existingAlias = getAliasList().getTalkgroupAlias(patchGroupID, false);
|
||||
|
||||
if(existingAlias instanceof PatchGroupAlias)
|
||||
{
|
||||
patchGroupAlias = (PatchGroupAlias)existingAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
patchGroupAlias = new PatchGroupAlias();
|
||||
|
||||
patchGroupAlias.addAliasID(new TalkgroupID(patchGroupID));
|
||||
|
||||
if(existingAlias != null)
|
||||
{
|
||||
getAliasList().removeAlias(existingAlias);
|
||||
|
||||
patchGroupAlias.setPatchGroupAlias(existingAlias);
|
||||
}
|
||||
|
||||
getAliasList().addAlias(patchGroupAlias);
|
||||
}
|
||||
|
||||
if(patchGroupAlias != null)
|
||||
{
|
||||
patchGroupAlias.setPatchedTalkgroupIDs(patchedTalkgroups);
|
||||
|
||||
patchGroupAlias.clearPatchedAliases();
|
||||
|
||||
for(String patchedTalkgroup : patchedTalkgroups)
|
||||
{
|
||||
Alias patchedAlias = getAliasList().getTalkgroupAlias(patchedTalkgroup);
|
||||
|
||||
if(patchedAlias != null)
|
||||
{
|
||||
patchGroupAlias.addPatchedAlias(patchedAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the temporary patch group alias from the alias list
|
||||
*/
|
||||
private void removePatchGroupAlias(String patchGroupID)
|
||||
{
|
||||
Alias alias = getAliasList().getTalkgroupAlias(patchGroupID);
|
||||
|
||||
if(alias instanceof PatchGroupAlias)
|
||||
{
|
||||
PatchGroupAlias patchGroupAlias = (PatchGroupAlias)alias;
|
||||
|
||||
getAliasList().removeAlias(patchGroupAlias);
|
||||
|
||||
//Replace our temporary patch group alias with the original alias for the patch group ID
|
||||
if(patchGroupAlias.hasPatchGroupAlias())
|
||||
{
|
||||
getAliasList().addAlias(patchGroupAlias.getPatchGroupAlias());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a traffic channel allocation message
|
||||
*/
|
||||
private void processTSBKChannelGrant(TSBKMessage message)
|
||||
{
|
||||
//Cleanup patch groups - auto-expire any patch groups before we allocate a channel
|
||||
mPatchGroupManager.cleanupPatchGroups();
|
||||
|
||||
String channel = null;
|
||||
String from = null;
|
||||
String to = null;
|
||||
|
||||
102
src/module/decode/p25/PatchGroup.java
Normal file
102
src/module/decode/p25/PatchGroup.java
Normal file
@@ -0,0 +1,102 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package module.decode.p25;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PatchGroup
|
||||
{
|
||||
private long mExpireThreshold = 5000; //5 seconds
|
||||
private long mLastUpdated;
|
||||
private String mPatchGroupID;
|
||||
private List<String> mPatchedGroups = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs a patch group with the specified patch group ID
|
||||
* @param patchGroupID that identifies this patch group
|
||||
*/
|
||||
public PatchGroup(String patchGroupID)
|
||||
{
|
||||
mPatchGroupID = patchGroupID;
|
||||
mLastUpdated = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch group ID for this patch group
|
||||
*/
|
||||
public String getPatchGroupID()
|
||||
{
|
||||
return mPatchGroupID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the patched group to this patch group. Duplicate patched groups are ignored.
|
||||
*
|
||||
* Note: the patch group ID will not be added as a patched group, to avoid circular dependencies.
|
||||
*
|
||||
* @return true if the patched group was added to this patch group
|
||||
*/
|
||||
public boolean addPatchedGroup(String patchedGroup)
|
||||
{
|
||||
if(patchedGroup != null && !patchedGroup.equals(mPatchGroupID) && !mPatchedGroups.contains(patchedGroup))
|
||||
{
|
||||
mPatchedGroups.add(patchedGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patched talkgroups that are part of this patch group.
|
||||
*/
|
||||
public List<String> getPatchedGroups()
|
||||
{
|
||||
return mPatchedGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the timestamp for this patch group.
|
||||
*/
|
||||
public void updateTimestamp()
|
||||
{
|
||||
mLastUpdated = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this patch group is expired, meaning that it hasn't been updated in the past (expire
|
||||
* threshold) seconds.
|
||||
*/
|
||||
public boolean isExpired()
|
||||
{
|
||||
return System.currentTimeMillis() - mLastUpdated > mExpireThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the patch group expiration threshold (default = 5000 ms). A patch group is considered expired if
|
||||
* no new updates have been received within the past (expire threshold) milliseconds
|
||||
*
|
||||
* @param expireThreshold in milliseconds
|
||||
*/
|
||||
public void setExpireThreshold(long expireThreshold)
|
||||
{
|
||||
mExpireThreshold = expireThreshold;
|
||||
}
|
||||
}
|
||||
243
src/module/decode/p25/PatchGroupManager.java
Normal file
243
src/module/decode/p25/PatchGroupManager.java
Normal file
@@ -0,0 +1,243 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package module.decode.p25;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import alias.PatchGroupAlias;
|
||||
import alias.id.talkgroup.TalkgroupID;
|
||||
import module.decode.event.CallEvent;
|
||||
import sample.Broadcaster;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class PatchGroupManager
|
||||
{
|
||||
private AliasList mAliasList;
|
||||
private List<PatchGroup> mPatchGroups = new ArrayList<>();
|
||||
private Broadcaster<CallEvent> mCallEventBroadcaster;
|
||||
|
||||
/**
|
||||
* Manages active P25 patch groups and auto-expires patch groups if not updated every 5 seconds.
|
||||
* @param aliasList to keep updated with patch group changes
|
||||
* @param broadcaster for rebroadcasting patch group related call events
|
||||
*/
|
||||
public PatchGroupManager(AliasList aliasList, Broadcaster<CallEvent> broadcaster)
|
||||
{
|
||||
mAliasList = aliasList;
|
||||
mCallEventBroadcaster = broadcaster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the patch group.
|
||||
*
|
||||
* @param patchGroupID of the patch group to remove
|
||||
*/
|
||||
public void removePatchGroup(String patchGroupID)
|
||||
{
|
||||
removePatchGroup(patchGroupID, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the patch group.
|
||||
*
|
||||
* @param patchGroupID of the patch group to remove
|
||||
* @param expired true if the patch group is being removed because it expired, false if we receive a
|
||||
* message commanding commanding a patch group delete.
|
||||
*/
|
||||
private void removePatchGroup(String patchGroupID, boolean expired)
|
||||
{
|
||||
PatchGroup patchGroup = getPatchGroup(patchGroupID);
|
||||
|
||||
if(patchGroup != null)
|
||||
{
|
||||
//Cleanup the alias list
|
||||
if(mAliasList != null)
|
||||
{
|
||||
Alias alias = mAliasList.getTalkgroupAlias(patchGroupID);
|
||||
|
||||
if(alias instanceof PatchGroupAlias)
|
||||
{
|
||||
PatchGroupAlias patchGroupAlias = (PatchGroupAlias)alias;
|
||||
|
||||
mAliasList.removeAlias(patchGroupAlias);
|
||||
|
||||
//Replace our temporary patch group alias with the original alias for the patch group ID
|
||||
if(patchGroupAlias.hasPatchGroupAlias())
|
||||
{
|
||||
mAliasList.addAlias(patchGroupAlias.getPatchGroupAlias());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mPatchGroups.remove(patchGroup);
|
||||
|
||||
if(mCallEventBroadcaster != null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append((expired ? "EXPIRED " : "DELETED "));
|
||||
sb.append("PATCH GROUP:").append(patchGroup.getPatchGroupID());
|
||||
sb.append(" ").append(patchGroup.getPatchedGroups());
|
||||
|
||||
|
||||
mCallEventBroadcaster.broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.PATCH_GROUP_DELETE)
|
||||
.to(patchGroup.getPatchGroupID())
|
||||
.details(sb.toString())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds/updates a patch group alias to the alias list containing aliases for each of the patched talkgroups. If the
|
||||
* patch group alias already exists, any patched talkgroups will be removed from the existing patch group alias and
|
||||
* replaced with the aliases corresponding to the patched talkgroup aliases.
|
||||
*
|
||||
* @param patchGroupID for the patch group
|
||||
* @param patchedTalkgroups containing the talkgroup IDs for each of the patched talkgroups
|
||||
*/
|
||||
public void updatePatchGroup(String patchGroupID, List<String> patchedTalkgroups)
|
||||
{
|
||||
boolean updated = false;
|
||||
|
||||
PatchGroup patchGroup = getPatchGroup(patchGroupID);
|
||||
|
||||
if(patchGroup == null)
|
||||
{
|
||||
//Remove any expired patch groups before we add a new one
|
||||
cleanupPatchGroups();
|
||||
patchGroup = new PatchGroup(patchGroupID);
|
||||
mPatchGroups.add(patchGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
patchGroup.updateTimestamp();
|
||||
}
|
||||
|
||||
for(String patchedGroup: patchedTalkgroups)
|
||||
{
|
||||
if(patchGroup.addPatchedGroup(patchedGroup))
|
||||
{
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
//If we make any changes to the patch group, update the patch group alias
|
||||
if(updated)
|
||||
{
|
||||
PatchGroupAlias patchGroupAlias = null;
|
||||
|
||||
//Check for an existing alias for the patch talkgroup - do not include wildcard aliases
|
||||
if(mAliasList != null)
|
||||
{
|
||||
Alias existingAlias = mAliasList.getTalkgroupAlias(patchGroupID, false);
|
||||
|
||||
if(existingAlias instanceof PatchGroupAlias)
|
||||
{
|
||||
patchGroupAlias = (PatchGroupAlias)existingAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
patchGroupAlias = new PatchGroupAlias();
|
||||
|
||||
patchGroupAlias.addAliasID(new TalkgroupID(patchGroupID));
|
||||
|
||||
if(existingAlias != null)
|
||||
{
|
||||
mAliasList.removeAlias(existingAlias);
|
||||
|
||||
patchGroupAlias.setPatchGroupAlias(existingAlias);
|
||||
}
|
||||
|
||||
mAliasList.addAlias(patchGroupAlias);
|
||||
}
|
||||
|
||||
if(patchGroupAlias != null)
|
||||
{
|
||||
patchGroupAlias.setPatchedTalkgroupIDs(patchGroup.getPatchedGroups());
|
||||
|
||||
patchGroupAlias.clearPatchedAliases();
|
||||
|
||||
for(String patchedTalkgroup : patchGroup.getPatchedGroups())
|
||||
{
|
||||
Alias patchedAlias = mAliasList.getTalkgroupAlias(patchedTalkgroup);
|
||||
|
||||
if(patchedAlias != null)
|
||||
{
|
||||
patchGroupAlias.addPatchedAlias(patchedAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mCallEventBroadcaster != null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("PATCH GROUP:").append(patchGroup.getPatchGroupID());
|
||||
sb.append(" ").append(patchGroup.getPatchedGroups());
|
||||
|
||||
mCallEventBroadcaster.broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.PATCH_GROUP_ADD)
|
||||
.aliasList(mAliasList)
|
||||
.details(sb.toString())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the patch group matching the patch group ID or null
|
||||
*/
|
||||
private PatchGroup getPatchGroup(String patchGroupID)
|
||||
{
|
||||
for(PatchGroup patchGroup: mPatchGroups)
|
||||
{
|
||||
if(patchGroup.getPatchGroupID().equals(patchGroupID))
|
||||
{
|
||||
return patchGroup;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the last updated timestamp on all patch groups and removes any patch groups that have not been
|
||||
* updated in the past 5 seconds
|
||||
*/
|
||||
public void cleanupPatchGroups()
|
||||
{
|
||||
Iterator<PatchGroup> it = mPatchGroups.iterator();
|
||||
|
||||
while(it.hasNext())
|
||||
{
|
||||
PatchGroup patchGroup = it.next();
|
||||
|
||||
if(patchGroup.isExpired())
|
||||
{
|
||||
it.remove();
|
||||
|
||||
removePatchGroup(patchGroup.getPatchGroupID(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user