Load DeviceSettings.config as an overlay on HikvisionServiceConfig
After loading serviceconfig.json, apply DeviceSettings.config values onto the existing config properties without changing runtime behavior or property names.main
parent
3bc691933a
commit
920b8d1e0c
|
|
@ -237,7 +237,7 @@ public sealed class HikvisionAttendanceWindowsService : ServiceBase
|
||||||
{
|
{
|
||||||
if (!File.Exists(configPath))
|
if (!File.Exists(configPath))
|
||||||
{
|
{
|
||||||
return new HikvisionServiceConfig
|
var missingCfg = new HikvisionServiceConfig
|
||||||
{
|
{
|
||||||
LogDirectory = @"C:\Users\Public\HikvisionAttendanceService",
|
LogDirectory = @"C:\Users\Public\HikvisionAttendanceService",
|
||||||
SqlConnectionString = "",
|
SqlConnectionString = "",
|
||||||
|
|
@ -284,6 +284,9 @@ public sealed class HikvisionAttendanceWindowsService : ServiceBase
|
||||||
UserSyncFaceCacheDirectory = "",
|
UserSyncFaceCacheDirectory = "",
|
||||||
SyncPolicies = new UserSyncPoliciesConfig()
|
SyncPolicies = new UserSyncPoliciesConfig()
|
||||||
};
|
};
|
||||||
|
ApplyDeviceSettingsOverlay(missingCfg, configPath);
|
||||||
|
NormalizeLoadedDeviceConfig(missingCfg);
|
||||||
|
return missingCfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
var raw = File.ReadAllText(configPath);
|
var raw = File.ReadAllText(configPath);
|
||||||
|
|
@ -296,6 +299,7 @@ public sealed class HikvisionAttendanceWindowsService : ServiceBase
|
||||||
{
|
{
|
||||||
var cfg = (HikvisionServiceConfig)serializer.ReadObject(ms);
|
var cfg = (HikvisionServiceConfig)serializer.ReadObject(ms);
|
||||||
ApplyEnvironmentOverrides(cfg);
|
ApplyEnvironmentOverrides(cfg);
|
||||||
|
ApplyDeviceSettingsOverlay(cfg, configPath);
|
||||||
NormalizeLoadedDeviceConfig(cfg);
|
NormalizeLoadedDeviceConfig(cfg);
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
@ -308,6 +312,7 @@ public sealed class HikvisionAttendanceWindowsService : ServiceBase
|
||||||
{
|
{
|
||||||
var cfg = (HikvisionServiceConfig)serializer.ReadObject(ms);
|
var cfg = (HikvisionServiceConfig)serializer.ReadObject(ms);
|
||||||
ApplyEnvironmentOverrides(cfg);
|
ApplyEnvironmentOverrides(cfg);
|
||||||
|
ApplyDeviceSettingsOverlay(cfg, configPath);
|
||||||
NormalizeLoadedDeviceConfig(cfg);
|
NormalizeLoadedDeviceConfig(cfg);
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +320,7 @@ public sealed class HikvisionAttendanceWindowsService : ServiceBase
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return new HikvisionServiceConfig
|
var fallbackCfg = new HikvisionServiceConfig
|
||||||
{
|
{
|
||||||
LogDirectory = @"C:\Users\Public\HikvisionAttendanceService",
|
LogDirectory = @"C:\Users\Public\HikvisionAttendanceService",
|
||||||
SqlConnectionString = "",
|
SqlConnectionString = "",
|
||||||
|
|
@ -362,6 +367,9 @@ public sealed class HikvisionAttendanceWindowsService : ServiceBase
|
||||||
UserSyncFaceCacheDirectory = "",
|
UserSyncFaceCacheDirectory = "",
|
||||||
SyncPolicies = new UserSyncPoliciesConfig()
|
SyncPolicies = new UserSyncPoliciesConfig()
|
||||||
};
|
};
|
||||||
|
ApplyDeviceSettingsOverlay(fallbackCfg, configPath);
|
||||||
|
NormalizeLoadedDeviceConfig(fallbackCfg);
|
||||||
|
return fallbackCfg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -481,6 +489,60 @@ public sealed class HikvisionAttendanceWindowsService : ServiceBase
|
||||||
cfg.DbPort = parsedPort;
|
cfg.DbPort = parsedPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overlays device-scope / template-direction settings from DeviceSettings.config
|
||||||
|
/// (same folder as serviceconfig.json). Property names and behavior are unchanged.
|
||||||
|
/// </summary>
|
||||||
|
private static void ApplyDeviceSettingsOverlay(HikvisionServiceConfig cfg, string serviceConfigPath)
|
||||||
|
{
|
||||||
|
if (cfg == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string dir;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dir = Path.GetDirectoryName(Path.GetFullPath(serviceConfigPath ?? "")) ?? "";
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
dir = "";
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(dir))
|
||||||
|
dir = AppContext.BaseDirectory;
|
||||||
|
|
||||||
|
var path = Path.Combine(dir, "DeviceSettings.config");
|
||||||
|
if (!File.Exists(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var raw = File.ReadAllText(path);
|
||||||
|
var serializer = new DataContractJsonSerializer(typeof(DeviceSettingsFile));
|
||||||
|
DeviceSettingsFile? overlay;
|
||||||
|
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(raw)))
|
||||||
|
overlay = serializer.ReadObject(ms) as DeviceSettingsFile;
|
||||||
|
if (overlay == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(overlay.MachineScopeMode))
|
||||||
|
cfg.MachineScopeMode = overlay.MachineScopeMode;
|
||||||
|
if (overlay.ScopedMachineIps != null)
|
||||||
|
cfg.ScopedMachineIps = new List<string>(overlay.ScopedMachineIps);
|
||||||
|
cfg.EnableTemplateDeviceToDbSync = overlay.EnableTemplateDeviceToDbSync;
|
||||||
|
cfg.EnableTemplateDbToDeviceSync = overlay.EnableTemplateDbToDeviceSync;
|
||||||
|
if (overlay.SourceMachineIp != null)
|
||||||
|
cfg.SourceMachineIp = overlay.SourceMachineIp;
|
||||||
|
if (overlay.TargetMachineIps != null)
|
||||||
|
cfg.TargetMachineIps = new List<string>(overlay.TargetMachineIps);
|
||||||
|
if (overlay.SyncEmployeeIds != null)
|
||||||
|
cfg.SyncEmployeeIds = new List<string>(overlay.SyncEmployeeIds);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Keep serviceconfig / defaults if DeviceSettings.config cannot be parsed.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void NormalizeLoadedDeviceConfig(HikvisionServiceConfig? cfg)
|
private static void NormalizeLoadedDeviceConfig(HikvisionServiceConfig? cfg)
|
||||||
{
|
{
|
||||||
if (cfg == null)
|
if (cfg == null)
|
||||||
|
|
@ -524,6 +586,32 @@ public sealed class HikvisionAttendanceWindowsService : ServiceBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Device-scope and template-direction settings loaded from DeviceSettings.config.</summary>
|
||||||
|
[DataContract]
|
||||||
|
internal sealed class DeviceSettingsFile
|
||||||
|
{
|
||||||
|
[DataMember]
|
||||||
|
public string MachineScopeMode { get; set; } = "CENTRAL";
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public List<string> ScopedMachineIps { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public bool EnableTemplateDeviceToDbSync { get; set; }
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public bool EnableTemplateDbToDeviceSync { get; set; }
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public string SourceMachineIp { get; set; } = "";
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public List<string> TargetMachineIps { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public List<string> SyncEmployeeIds { get; set; } = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Policies for multi-device user/face sync (ISAPI). Loaded from service JSON only.</summary>
|
/// <summary>Policies for multi-device user/face sync (ISAPI). Loaded from service JSON only.</summary>
|
||||||
[DataContract]
|
[DataContract]
|
||||||
internal sealed class UserSyncPoliciesConfig
|
internal sealed class UserSyncPoliciesConfig
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue