阶段性批量提交
This commit is contained in:
227
SHH.CameraSdk/Configs/ServiceConfig.cs
Normal file
227
SHH.CameraSdk/Configs/ServiceConfig.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
namespace SHH.CameraSdk;
|
||||
|
||||
/// <summary>
|
||||
/// 全局服务配置模型 (V3 最终版)
|
||||
/// <para>负责解析命令行参数,构建网络拓扑和身份标识</para>
|
||||
/// </summary>
|
||||
public class ServiceConfig
|
||||
{
|
||||
// ==========================================
|
||||
// 1. 身份与进程属性
|
||||
// ==========================================
|
||||
|
||||
/// <summary>
|
||||
/// 父进程 PID (用于哨兵守护,--pid)
|
||||
/// </summary>
|
||||
public int ParentPid { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用完整标识 (例如 "CameraApp_01", --appid)
|
||||
/// </summary>
|
||||
public string AppId { get; private set; } = "Unknown_01";
|
||||
|
||||
/// <summary>
|
||||
/// 【核心】从 AppId 自动提取的数字编号
|
||||
/// <para>规则:取最后一个下划线后的数字</para>
|
||||
/// <para>示例:"CameraApp_05" -> 5</para>
|
||||
/// </summary>
|
||||
public int NumericId { get; private set; } = 1;
|
||||
|
||||
// ==========================================
|
||||
// 2. 网络连接属性 (分流)
|
||||
// ==========================================
|
||||
|
||||
/// <summary>
|
||||
/// 视频流目标地址列表 (对应 & 符号左侧)
|
||||
/// <para>ZeroMQBridgeWorker 使用此列表</para>
|
||||
/// </summary>
|
||||
public List<string> VideoEndpoints { get; private set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 指令控制目标地址列表 (对应 & 符号右侧)
|
||||
/// <para>CommandClientWorker 使用此列表</para>
|
||||
/// </summary>
|
||||
public List<string> CommandEndpoints { get; private set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// WebAPI 基础端口 (--ports 的第一个值)
|
||||
/// </summary>
|
||||
public int BasePort { get; private set; } = 5000;
|
||||
|
||||
/// <summary>
|
||||
/// 端口扫描范围 (--ports 的第二个值)
|
||||
/// </summary>
|
||||
public int MaxPortRange { get; private set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// 网络模式 (--mode)
|
||||
/// </summary>
|
||||
public NetworkMode Mode { get; private set; } = NetworkMode.Passive;
|
||||
|
||||
// ==========================================
|
||||
// 3. 辅助属性
|
||||
// ==========================================
|
||||
|
||||
/// <summary>
|
||||
/// 是否需要执行 Connect 操作
|
||||
/// </summary>
|
||||
public bool ShouldConnect => Mode == NetworkMode.Active || Mode == NetworkMode.Hybrid;
|
||||
|
||||
// ==========================================
|
||||
// 4. 解析入口 (Factory Method)
|
||||
// ==========================================
|
||||
|
||||
public static ServiceConfig BuildFromArgs(string[] args)
|
||||
{
|
||||
var config = new ServiceConfig();
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
// 1. 预处理 Key
|
||||
var key = args[i].ToLower().Trim();
|
||||
|
||||
// 2. 预取 Value (如果存在且不是下一个 flag)
|
||||
var value = (i + 1 < args.Length) ? args[i + 1] : string.Empty;
|
||||
|
||||
// 简单判断:如果 value 以 -- 开头,说明当前 key 是开关,或者参数值缺失
|
||||
if (value.StartsWith("--")) value = string.Empty;
|
||||
|
||||
bool consumed = false; // 标记是否消耗了下一个参数
|
||||
|
||||
// 3. 匹配参数
|
||||
switch (key)
|
||||
{
|
||||
case "--pid":
|
||||
if (int.TryParse(value, out int pid)) config.ParentPid = pid;
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case "--appid":
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
config.AppId = value;
|
||||
// ★★★ 立即解析数字编号 ★★★
|
||||
config.NumericId = ParseIdFromAppId(value);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case "--uris":
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
// ★★★ 解析复杂 URI 字符串 ★★★
|
||||
ParseUris(config, value);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case "--mode":
|
||||
if (int.TryParse(value, out int m) && Enum.IsDefined(typeof(NetworkMode), m))
|
||||
{
|
||||
config.Mode = (NetworkMode)m;
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case "--ports":
|
||||
// 格式: "BasePort,Range" -> "6003,100"
|
||||
if (!string.IsNullOrWhiteSpace(value) && value.Contains(","))
|
||||
{
|
||||
var parts = value.Split(',');
|
||||
if (parts.Length >= 1)
|
||||
{
|
||||
if (int.TryParse(parts[0], out int baseP)) config.BasePort = baseP;
|
||||
}
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
if (int.TryParse(parts[1], out int range)) config.MaxPortRange = range;
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// 4. 如果消耗了 Value,跳过下一个索引
|
||||
if (consumed) i++;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 5. 核心解析算法实现
|
||||
// ==========================================
|
||||
|
||||
/// <summary>
|
||||
/// 算法:提取下划线后的数字
|
||||
/// </summary>
|
||||
private static int ParseIdFromAppId(string appId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(appId)) return 1;
|
||||
|
||||
// 查找最后一个下划线
|
||||
int lastIdx = appId.LastIndexOf('_');
|
||||
|
||||
// 确保下划线存在,且后面还有字符
|
||||
if (lastIdx >= 0 && lastIdx < appId.Length - 1)
|
||||
{
|
||||
string numPart = appId.Substring(lastIdx + 1);
|
||||
if (int.TryParse(numPart, out int id))
|
||||
{
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
// 解析失败默认返回 1
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 算法:解析 URI 列表并分流
|
||||
/// <para>格式: IP,VideoPort&CommandPort</para>
|
||||
/// <para>空缺处理: "&6001" (仅指令), "6002&" (仅视频)</para>
|
||||
/// </summary>
|
||||
private static void ParseUris(ServiceConfig config, string rawValue)
|
||||
{
|
||||
// 1. 按分号拆分不同主机配置
|
||||
// "127.0.0.1,6002&6001; 192.168.1.5,&6001"
|
||||
var groups = rawValue.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
// 2. 按逗号拆分 IP 和 端口段
|
||||
var hostParts = group.Split(',');
|
||||
if (hostParts.Length < 2) continue; // 格式非法
|
||||
|
||||
string ip = hostParts[0].Trim();
|
||||
string portSection = hostParts[1].Trim(); // "6002&6001"
|
||||
|
||||
// 3. 按 & 拆分端口 (注意:不要 RemoveEmptyEntries,位置很重要)
|
||||
var ports = portSection.Split('&');
|
||||
|
||||
// --- 索引 0: 视频端口 ---
|
||||
if (ports.Length > 0)
|
||||
{
|
||||
string p = ports[0].Trim();
|
||||
if (!string.IsNullOrWhiteSpace(p) && int.TryParse(p, out int port))
|
||||
{
|
||||
string uri = $"tcp://{ip}:{port}";
|
||||
if (!config.VideoEndpoints.Contains(uri))
|
||||
config.VideoEndpoints.Add(uri);
|
||||
}
|
||||
}
|
||||
|
||||
// --- 索引 1: 指令端口 ---
|
||||
if (ports.Length > 1)
|
||||
{
|
||||
string p = ports[1].Trim();
|
||||
if (!string.IsNullOrWhiteSpace(p) && int.TryParse(p, out int port))
|
||||
{
|
||||
string uri = $"tcp://{ip}:{port}";
|
||||
if (!config.CommandEndpoints.Contains(uri))
|
||||
config.CommandEndpoints.Add(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user