|
|
|
@ -9,7 +9,7 @@
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Copyright (C) 2024-2025 Caleb, K4PHP
|
|
|
|
* Copyright (C) 2024-2025 Caleb, K4PHP
|
|
|
|
* Copyright (C) 2025 Bryan Biedenkapp, N2PLL
|
|
|
|
* Copyright (C) 2025 Bryan Biedenkapp, N2PLL
|
|
|
|
* Copyright (C) 2025 Steven Jennison, KD8RHO
|
|
|
|
* Copyright (C) 2025 Steven Jennison, KD8RHO
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
@ -22,6 +22,16 @@ namespace dvmconsole
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public class Codeplug
|
|
|
|
public class Codeplug
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Enumeration of channel modes.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
public enum ChannelMode
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
DMR = 0,
|
|
|
|
|
|
|
|
NXDN = 1,
|
|
|
|
|
|
|
|
P25 = 2
|
|
|
|
|
|
|
|
} // public enum ChannelMode
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** Properties
|
|
|
|
** Properties
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@ -31,11 +41,11 @@ namespace dvmconsole
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string KeyFile { get; set; } = null;
|
|
|
|
public string KeyFile { get; set; } = null;
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// List of systems.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public List<System> Systems { get; set; }
|
|
|
|
public List<System> Systems { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// List of zones.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public List<Zone> Zones { get; set; }
|
|
|
|
public List<Zone> Zones { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
@ -53,41 +63,46 @@ namespace dvmconsole
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Textual name for system.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Name { get; set; }
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Textual identity string reported to the FNE core.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Identity { get; set; }
|
|
|
|
public string Identity { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// IP/hostname of the FNE.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Address { get; set; }
|
|
|
|
public string Address { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Port number for the FNE connection.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
public int Port { get; set; }
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// Authentication password.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Password { get; set; }
|
|
|
|
public string Password { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Preshared Encryption key.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string PresharedKey { get; set; }
|
|
|
|
public string PresharedKey { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Flag indicating whether or not the connection to the FNE is encrypted.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public bool Encrypted { get; set; }
|
|
|
|
public bool Encrypted { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Unique Peer ID.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public uint PeerId { get; set; }
|
|
|
|
public uint PeerId { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Unique Radio ID.
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
public int Port { get; set; }
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Rid { get; set; }
|
|
|
|
public string Rid { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
@ -112,7 +127,7 @@ namespace dvmconsole
|
|
|
|
} // public class System
|
|
|
|
} // public class System
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Data structure representation of the data for a zone.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public class Zone
|
|
|
|
public class Zone
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -121,17 +136,17 @@ namespace dvmconsole
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Textual name for zone.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Name { get; set; }
|
|
|
|
public string Name { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// List of channels in the zone.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public List<Channel> Channels { get; set; }
|
|
|
|
public List<Channel> Channels { get; set; }
|
|
|
|
} // public class Zone
|
|
|
|
} // public class Zone
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Data structure representation of the data for a channel.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public class Channel
|
|
|
|
public class Channel
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -140,31 +155,31 @@ namespace dvmconsole
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Textual name for channel.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Name { get; set; }
|
|
|
|
public string Name { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Textual name for system channel is a member of.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string System { get; set; }
|
|
|
|
public string System { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Talkgroup ID.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Tgid { get; set; }
|
|
|
|
public string Tgid { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// DMR Timeslot.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string EncryptionKey { get; set; }
|
|
|
|
public int Slot { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Textual algorithm name.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Algo { get; set; } = "none";
|
|
|
|
public string Algo { get; set; } = "none";
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Encryption Key ID.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string KeyId { get; set; }
|
|
|
|
public string KeyId { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Digital Voice Mode.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public string Mode { get; set; } = "p25";
|
|
|
|
public string Mode { get; set; } = "p25";
|
|
|
|
|
|
|
|
|
|
|
|
@ -173,7 +188,7 @@ namespace dvmconsole
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Helper to return the key ID as a numeric value from a string.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <returns></returns>
|
|
|
|
public ushort GetKeyId()
|
|
|
|
public ushort GetKeyId()
|
|
|
|
@ -182,7 +197,7 @@ namespace dvmconsole
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Helper to return the algorithm ID from the configured algorithm type string.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <returns></returns>
|
|
|
|
public byte GetAlgoId()
|
|
|
|
public byte GetAlgoId()
|
|
|
|
@ -199,42 +214,18 @@ namespace dvmconsole
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// Helper to return the channel mode.
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
|
|
public byte[] GetEncryptionKey()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (EncryptionKey == null)
|
|
|
|
|
|
|
|
return [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return EncryptionKey.Split(',').Select(s => Convert.ToByte(s.Trim(), 16)).ToArray();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <returns></returns>
|
|
|
|
public ChannelMode GetChannelMode()
|
|
|
|
public ChannelMode GetChannelMode()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (Enum.TryParse(typeof(ChannelMode), Mode, ignoreCase: true, out var result))
|
|
|
|
if (Enum.TryParse(typeof(ChannelMode), Mode, ignoreCase: true, out var result))
|
|
|
|
{
|
|
|
|
|
|
|
|
return (ChannelMode)result;
|
|
|
|
return (ChannelMode)result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ChannelMode.P25;
|
|
|
|
return ChannelMode.P25;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // public class Channel
|
|
|
|
} // public class Channel
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
public enum ChannelMode
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
DMR = 0,
|
|
|
|
|
|
|
|
NXDN = 1,
|
|
|
|
|
|
|
|
P25 = 2
|
|
|
|
|
|
|
|
} // public enum ChannelMode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// Helper to return a system by looking up a <see cref="Channel"/>
|
|
|
|
/// Helper to return a system by looking up a <see cref="Channel"/>
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
@ -252,9 +243,9 @@ namespace dvmconsole
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <returns></returns>
|
|
|
|
public System GetSystemForChannel(string channelName)
|
|
|
|
public System GetSystemForChannel(string channelName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
foreach (var zone in Zones)
|
|
|
|
foreach (Zone zone in Zones)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var channel = zone.Channels.FirstOrDefault(c => c.Name == channelName);
|
|
|
|
Channel channel = zone.Channels.FirstOrDefault(c => c.Name == channelName);
|
|
|
|
if (channel != null)
|
|
|
|
if (channel != null)
|
|
|
|
return Systems.FirstOrDefault(s => s.Name == channel.System);
|
|
|
|
return Systems.FirstOrDefault(s => s.Name == channel.System);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -269,9 +260,9 @@ namespace dvmconsole
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <returns></returns>
|
|
|
|
public Channel GetChannelByName(string channelName)
|
|
|
|
public Channel GetChannelByName(string channelName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
foreach (var zone in Zones)
|
|
|
|
foreach (Zone zone in Zones)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var channel = zone.Channels.FirstOrDefault(c => c.Name == channelName);
|
|
|
|
Channel channel = zone.Channels.FirstOrDefault(c => c.Name == channelName);
|
|
|
|
if (channel != null)
|
|
|
|
if (channel != null)
|
|
|
|
return channel;
|
|
|
|
return channel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|