Fix DB_TO_DEVICE HTTP restore so deleted users get face templates on device.
Use EmpIds from config when restoring from DB, and push templates via a two-step setuserinfo (create user, then backupnum/record or face) matching the F710X web API. Co-authored-by: Cursor <cursoragent@cursor.com>main
parent
6867cb90e7
commit
5424d0abb8
|
|
@ -6,12 +6,13 @@
|
|||
providerName="MySql.Data.MySqlClient" />
|
||||
</connectionStrings>
|
||||
<appSettings>
|
||||
<add key="ATTENDANCE_SCOPE" value="CENTRAL" />
|
||||
<!--<add key="ATTENDANCE_SCOPE" value="SITE" />-->
|
||||
<!-- <add key="ATTENDANCE_SCOPE" value="CENTRAL" /> -->
|
||||
<add key="ATTENDANCE_SCOPE" value="SITE" />
|
||||
<add key="ATTENDANCE_JOB_INTERVAL_MINUTES" value="20" />
|
||||
<add key="TEMPLATE_JOB_INTERVAL_MINUTES" value="240" />
|
||||
<add key="TEMPLATE_SYNC_ENABLED" value="true" />
|
||||
<add key="TRANSFER_MODE" value="DEVICE_TO_DB" />
|
||||
<!-- <add key="TRANSFER_MODE" value="DB_TO_DEVICE" /> -->
|
||||
<add key="DEVICE_SETTINGS_PATH" value="DeviceSettings.xml" />
|
||||
<add key="TEMPLATE_VERIFY_AFTER_PUSH" value="true" />
|
||||
<add key="TEMPLATE_DEVICE_DELAY_MS" value="0" />
|
||||
|
|
|
|||
|
|
@ -104,6 +104,24 @@ namespace HanvonF710XAttendanceService
|
|||
}
|
||||
}
|
||||
|
||||
public string GetEmployeeNameForMachine(MySqlConnection connection, string machineId, string serialNumber)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(machineId) || string.IsNullOrWhiteSpace(serialNumber)) return null;
|
||||
const string query =
|
||||
"SELECT employee_name FROM hrms.attendance_machine_user " +
|
||||
"WHERE machine_id = @MachineId AND serial_number = @SerialNumber AND is_deleted = 0 LIMIT 1";
|
||||
using (var cmd = new MySqlCommand(query, connection))
|
||||
{
|
||||
cmd.CommandTimeout = 60;
|
||||
cmd.Parameters.AddWithValue("@MachineId", machineId);
|
||||
cmd.Parameters.AddWithValue("@SerialNumber", serialNumber.Trim());
|
||||
var result = cmd.ExecuteScalar();
|
||||
if (result == null || result == DBNull.Value) return null;
|
||||
var name = result.ToString()?.Trim();
|
||||
return string.IsNullOrWhiteSpace(name) ? null : name;
|
||||
}
|
||||
}
|
||||
|
||||
private List<AttendanceMachineUser> getDBUsers(MySqlDataReader reader)
|
||||
{
|
||||
List<AttendanceMachineUser> DbUsers = new List<AttendanceMachineUser>();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<DeviceSettings Mode="Multi" SiteId="2">
|
||||
<!--<Device IpAddress="192.168.70.14" Enabled="true" />-->
|
||||
<Device IpAddress="192.168.86.2" Enabled="true" />
|
||||
<Device IpAddress="192.168.90.89" Enabled="true" />
|
||||
|
||||
<TemplateTransfer Enabled="false">
|
||||
<TemplateTransfer Enabled="true">
|
||||
<Job Id="1"
|
||||
Enabled="true"
|
||||
SourceIp="192.168.86.7"
|
||||
EmpIds="7044">
|
||||
<Target Ip="192.168.86.4" />
|
||||
SourceIp="192.168.90.89"
|
||||
EmpIds="15399,17003">
|
||||
<Target Ip="192.168.90.89" />
|
||||
</Job>
|
||||
</TemplateTransfer>
|
||||
|
||||
|
|
|
|||
|
|
@ -196,6 +196,121 @@ namespace HanvonF710XAttendanceService
|
|||
}
|
||||
}
|
||||
|
||||
public static string NormalizeFaceTemplatePayload(byte[] blob, out string pushMode)
|
||||
{
|
||||
pushMode = "record";
|
||||
if (blob == null || blob.Length == 0) return null;
|
||||
|
||||
if (blob.Length >= 3 && blob[0] == 0xFF && blob[1] == 0xD8 && blob[2] == 0xFF)
|
||||
{
|
||||
pushMode = "face";
|
||||
return Convert.ToBase64String(blob);
|
||||
}
|
||||
|
||||
string text = Encoding.UTF8.GetString(blob).Trim();
|
||||
if (string.IsNullOrWhiteSpace(text)) return null;
|
||||
|
||||
if (text.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
int comma = text.IndexOf(',');
|
||||
if (comma >= 0) text = text.Substring(comma + 1);
|
||||
}
|
||||
|
||||
text = text.Replace("\r", "").Replace("\n", "").Trim();
|
||||
if (string.IsNullOrWhiteSpace(text)) return null;
|
||||
|
||||
try
|
||||
{
|
||||
byte[] decoded = Convert.FromBase64String(text);
|
||||
if (decoded.Length >= 3 && decoded[0] == 0xFF && decoded[1] == 0xD8 && decoded[2] == 0xFF)
|
||||
{
|
||||
pushMode = "face";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Biometric templates from getuserinfo may not decode as standard base64.
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public bool TryEnsureUser(int enrollId, string name, out string error)
|
||||
{
|
||||
error = null;
|
||||
try
|
||||
{
|
||||
var resp = Post(new Dictionary<string, object>
|
||||
{
|
||||
{ "cmd", "setuserinfo" },
|
||||
{ "password", _password },
|
||||
{ "enrollid", enrollId },
|
||||
{ "name", name ?? enrollId.ToString() },
|
||||
{ "department", "" },
|
||||
{ "shiftid", 1 },
|
||||
{ "admin", 0 },
|
||||
{ "pwd", 0 },
|
||||
{ "card", 0 },
|
||||
{ "zoneid", 0 },
|
||||
{ "groupid", 0 },
|
||||
{ "access_times", 0 },
|
||||
{ "verifymode", 0 },
|
||||
{ "birthday", "" },
|
||||
{ "starttime", "" },
|
||||
{ "endtime", "" },
|
||||
{ "userprofile", "" }
|
||||
});
|
||||
if (IsSuccess(resp)) return true;
|
||||
error = GetMsg(resp) ?? "setuserinfo failed";
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = ex.Message;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TrySetFaceTemplateRecord(int enrollId, string templatePayload, string pushMode, out string error)
|
||||
{
|
||||
error = null;
|
||||
if (string.IsNullOrWhiteSpace(templatePayload))
|
||||
{
|
||||
error = "template record is empty";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var payload = new Dictionary<string, object>
|
||||
{
|
||||
{ "cmd", "setuserinfo" },
|
||||
{ "password", _password },
|
||||
{ "enrollid", enrollId }
|
||||
};
|
||||
|
||||
if (string.Equals(pushMode, "face", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
payload["face"] = templatePayload;
|
||||
}
|
||||
else
|
||||
{
|
||||
payload["backupnum"] = GetIntSetting("DEVICE_FACE_BACKUPNUM", 50);
|
||||
payload["record"] = templatePayload;
|
||||
}
|
||||
|
||||
var resp = Post(payload);
|
||||
if (IsSuccess(resp)) return true;
|
||||
error = GetMsg(resp) ?? "setuserinfo template push failed";
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = ex.Message;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetFaceRecord(int enrollId, out string recordBase64, out string name, out string error)
|
||||
{
|
||||
recordBase64 = null;
|
||||
|
|
@ -231,6 +346,43 @@ namespace HanvonF710XAttendanceService
|
|||
}
|
||||
}
|
||||
|
||||
public bool TryRestoreUserWithFaceTemplate(int enrollId, string name, string templatePayload, string pushMode, out string error)
|
||||
{
|
||||
error = null;
|
||||
if (string.IsNullOrWhiteSpace(templatePayload))
|
||||
{
|
||||
error = "template record is empty";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryEnsureUser(enrollId, name, out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int delayMs = GetIntSetting("TEMPLATE_DEVICE_DELAY_MS", 300);
|
||||
if (delayMs > 0)
|
||||
{
|
||||
System.Threading.Thread.Sleep(delayMs);
|
||||
}
|
||||
|
||||
if (!TrySetFaceTemplateRecord(enrollId, templatePayload, pushMode, out error))
|
||||
{
|
||||
string altMode = string.Equals(pushMode, "face", StringComparison.OrdinalIgnoreCase) ? "record" : "face";
|
||||
if (!TrySetFaceTemplateRecord(enrollId, templatePayload, altMode, out error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UserHasFaceTemplate(int enrollId, out string error)
|
||||
{
|
||||
return TryGetFaceRecord(enrollId, out _, out _, out error);
|
||||
}
|
||||
|
||||
private Dictionary<string, object> Post(Dictionary<string, object> payload)
|
||||
{
|
||||
string body = _json.Serialize(payload);
|
||||
|
|
|
|||
|
|
@ -128,24 +128,50 @@ namespace HanvonF710XAttendanceService
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!TryGetEmployeeIdsFromDevice(sourceMachine, out var employeeIds, logs, job.Id))
|
||||
if (mode == TemplateTransferMode.DB_TO_DEVICE)
|
||||
{
|
||||
List<string> idsForTransfer;
|
||||
if (job.EmpIds != null && job.EmpIds.Count > 0)
|
||||
{
|
||||
// Restore from DB even when user was deleted from source device.
|
||||
idsForTransfer = job.EmpIds
|
||||
.Where(id => !string.IsNullOrWhiteSpace(id))
|
||||
.Select(id => id.Trim())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
logs.Add($"[TemplateJob {job.Id}] DB_TO_DEVICE using EmpIds from config (source device list skipped): {string.Join(",", idsForTransfer)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!TryGetEmployeeIdsFromDevice(sourceMachine, out var employeeIds, logs, job.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (employeeIds.Count == 0)
|
||||
{
|
||||
logs.Add($"[TemplateJob {job.Id}] Source device returned 0 employee IDs.");
|
||||
continue;
|
||||
}
|
||||
idsForTransfer = employeeIds;
|
||||
}
|
||||
TransferDbToDevice(job, idsForTransfer, targetMachines, connection, logs);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TryGetEmployeeIdsFromDevice(sourceMachine, out var deviceEmployeeIds, logs, job.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (employeeIds.Count == 0)
|
||||
if (deviceEmployeeIds.Count == 0)
|
||||
{
|
||||
logs.Add($"[TemplateJob {job.Id}] Source device returned 0 employee IDs.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mode == TemplateTransferMode.DB_TO_DEVICE)
|
||||
if (mode == TemplateTransferMode.DEVICE_TO_DEVICE)
|
||||
{
|
||||
TransferDbToDevice(job, employeeIds, targetMachines, connection, logs);
|
||||
}
|
||||
else if (mode == TemplateTransferMode.DEVICE_TO_DEVICE)
|
||||
{
|
||||
TransferDeviceToDevice(job.Id, sourceMachine, employeeIds, targetMachines, logs);
|
||||
TransferDeviceToDevice(job.Id, sourceMachine, deviceEmployeeIds, targetMachines, logs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -678,9 +704,6 @@ namespace HanvonF710XAttendanceService
|
|||
|
||||
foreach (var target in targets)
|
||||
{
|
||||
string targetDevInfo = target.Machine.GetDeviceInfo();
|
||||
var callback = new CallBack(Program.BeCalled);
|
||||
|
||||
int ok = 0;
|
||||
int fail = 0;
|
||||
int verifyOk = 0;
|
||||
|
|
@ -688,53 +711,71 @@ namespace HanvonF710XAttendanceService
|
|||
|
||||
logs.Add($"[TemplateTransfer] job={job.Id} target_ip={target.Machine.MachineIp} total_templates={totalTemplates} batch_size={batchSize} total_batches={batches.Count}");
|
||||
|
||||
for (int bi = 0; bi < batches.Count; bi++)
|
||||
if (DeviceProtocol.UseHttp())
|
||||
{
|
||||
var swBatch = Stopwatch.StartNew();
|
||||
int bAttempted = 0;
|
||||
int bOk = 0;
|
||||
int bFail = 0;
|
||||
int bVerifyOk = 0;
|
||||
int bVerifyFail = 0;
|
||||
|
||||
foreach (var kvp in batches[bi])
|
||||
var httpClient = HanvonHttpApiClient.ForMachine(target.Machine);
|
||||
if (!httpClient.TryLogin(out string loginErr))
|
||||
{
|
||||
bAttempted++;
|
||||
string empId = kvp.Key;
|
||||
string templateStr = Encoding.UTF8.GetString(kvp.Value ?? Array.Empty<byte>());
|
||||
if (!TemplateParser.TryBuildSetEmployeeCommand(templateStr, out var setCmd))
|
||||
{
|
||||
fail++;
|
||||
bFail++;
|
||||
logs.Add($"[TemplateJob {job.Id}] Build SetEmployee failed. emp={empId} target={target.Machine.MachineIp}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} send=FAIL reason=BuildSetEmployee");
|
||||
continue;
|
||||
}
|
||||
logs.Add($"[TemplateJob {job.Id}] HTTP login failed for target. ip={target.Machine.MachineIp} err={loginErr}");
|
||||
Program.RecordUnreachableMachine(target.Machine, "DB_TO_DEVICE HTTP login: " + loginErr);
|
||||
continue;
|
||||
}
|
||||
|
||||
string response = "";
|
||||
uint recvLen = 0;
|
||||
int rc = Program.test(targetDevInfo, targetDevInfo.Length, setCmd, setCmd.Length, ref response, ref recvLen, callback);
|
||||
if (rc != 0 || (response != null && response.IndexOf("fail", StringComparison.OrdinalIgnoreCase) >= 0))
|
||||
{
|
||||
fail++;
|
||||
bFail++;
|
||||
logs.Add($"[TemplateJob {job.Id}] SetEmployee failed. emp={empId} target={target.Machine.MachineIp}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} send=FAIL rc={rc}");
|
||||
}
|
||||
else
|
||||
var machineUserDao = new AttendanceMachineUserDAO();
|
||||
|
||||
for (int bi = 0; bi < batches.Count; bi++)
|
||||
{
|
||||
var swBatch = Stopwatch.StartNew();
|
||||
int bAttempted = 0;
|
||||
int bOk = 0;
|
||||
int bFail = 0;
|
||||
int bVerifyOk = 0;
|
||||
int bVerifyFail = 0;
|
||||
|
||||
foreach (var kvp in batches[bi])
|
||||
{
|
||||
bAttempted++;
|
||||
string empId = kvp.Key;
|
||||
byte[] templateBlob = kvp.Value ?? Array.Empty<byte>();
|
||||
string recordBase64 = HanvonHttpApiClient.NormalizeFaceTemplatePayload(templateBlob, out string pushMode);
|
||||
if (string.IsNullOrWhiteSpace(recordBase64))
|
||||
{
|
||||
fail++;
|
||||
bFail++;
|
||||
logs.Add($"[TemplateJob {job.Id}] Empty template payload. emp={empId} blob_bytes={templateBlob.Length} target={target.Machine.MachineIp}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} send=FAIL reason=EmptyTemplate blob_bytes={templateBlob.Length}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!int.TryParse(empId, out int enrollId))
|
||||
{
|
||||
fail++;
|
||||
bFail++;
|
||||
logs.Add($"[TemplateJob {job.Id}] Invalid enroll id for HTTP setuserinfo. emp={empId} target={target.Machine.MachineIp}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} send=FAIL reason=InvalidEnrollId");
|
||||
continue;
|
||||
}
|
||||
|
||||
string displayName = machineUserDao.GetEmployeeNameForMachine(connection, target.Machine.MachineId, empId)
|
||||
?? empId;
|
||||
|
||||
if (!httpClient.TryRestoreUserWithFaceTemplate(enrollId, displayName, recordBase64, pushMode, out string pushErr))
|
||||
{
|
||||
fail++;
|
||||
bFail++;
|
||||
logs.Add($"[TemplateJob {job.Id}] HTTP template push failed. emp={empId} mode={pushMode} payload_len={recordBase64.Length} target={target.Machine.MachineIp} err={pushErr}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} mode={pushMode} payload_len={recordBase64.Length} send=FAIL err={pushErr}");
|
||||
continue;
|
||||
}
|
||||
|
||||
ok++;
|
||||
bOk++;
|
||||
logs.Add($"[TemplateJob {job.Id}] HTTP template push ok. emp={empId} name={displayName} mode={pushMode} payload_len={recordBase64.Length} target={target.Machine.MachineIp}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} send=OK");
|
||||
|
||||
if (verifyAfterPush)
|
||||
{
|
||||
string verifyCmd = "GetEmployee(id=\"" + empId + "\")";
|
||||
string verifyResp = "";
|
||||
uint verifyRecvLen = 0;
|
||||
int vrc = Program.test(targetDevInfo, targetDevInfo.Length, verifyCmd, verifyCmd.Length, ref verifyResp, ref verifyRecvLen, callback);
|
||||
bool success = vrc == 0 && verifyResp != null && verifyResp.IndexOf("success", StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
if (success)
|
||||
if (httpClient.UserHasFaceTemplate(enrollId, out string verifyErr))
|
||||
{
|
||||
verifyOk++;
|
||||
bVerifyOk++;
|
||||
|
|
@ -744,19 +785,96 @@ namespace HanvonF710XAttendanceService
|
|||
{
|
||||
verifyFail++;
|
||||
bVerifyFail++;
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} verify=FAIL rc={vrc}");
|
||||
logs.Add($"[TemplateJob {job.Id}] HTTP verify failed after push. emp={empId} target={target.Machine.MachineIp} err={verifyErr}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} verify=FAIL err={verifyErr}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delayMs > 0)
|
||||
if (delayMs > 0)
|
||||
{
|
||||
Thread.Sleep(delayMs);
|
||||
}
|
||||
|
||||
swBatch.Stop();
|
||||
logs.Add($"[TemplateTransferBatch] job={job.Id} target_ip={target.Machine.MachineIp} batch={bi + 1}/{batches.Count} attempted={bAttempted} ok={bOk} fail={bFail} verify_ok={bVerifyOk} verify_fail={bVerifyFail} duration_sec={Math.Round(swBatch.Elapsed.TotalSeconds, 1)}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string targetDevInfo = target.Machine.GetDeviceInfo();
|
||||
var callback = new CallBack(Program.BeCalled);
|
||||
|
||||
for (int bi = 0; bi < batches.Count; bi++)
|
||||
{
|
||||
System.Threading.Thread.Sleep(delayMs);
|
||||
}
|
||||
var swBatch = Stopwatch.StartNew();
|
||||
int bAttempted = 0;
|
||||
int bOk = 0;
|
||||
int bFail = 0;
|
||||
int bVerifyOk = 0;
|
||||
int bVerifyFail = 0;
|
||||
|
||||
swBatch.Stop();
|
||||
logs.Add($"[TemplateTransferBatch] job={job.Id} target_ip={target.Machine.MachineIp} batch={bi + 1}/{batches.Count} attempted={bAttempted} ok={bOk} fail={bFail} verify_ok={bVerifyOk} verify_fail={bVerifyFail} duration_sec={Math.Round(swBatch.Elapsed.TotalSeconds, 1)}");
|
||||
foreach (var kvp in batches[bi])
|
||||
{
|
||||
bAttempted++;
|
||||
string empId = kvp.Key;
|
||||
string templateStr = Encoding.UTF8.GetString(kvp.Value ?? Array.Empty<byte>());
|
||||
if (!TemplateParser.TryBuildSetEmployeeCommand(templateStr, out var setCmd))
|
||||
{
|
||||
fail++;
|
||||
bFail++;
|
||||
logs.Add($"[TemplateJob {job.Id}] Build SetEmployee failed. emp={empId} target={target.Machine.MachineIp}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} send=FAIL reason=BuildSetEmployee");
|
||||
continue;
|
||||
}
|
||||
|
||||
string response = "";
|
||||
uint recvLen = 0;
|
||||
int rc = Program.test(targetDevInfo, targetDevInfo.Length, setCmd, setCmd.Length, ref response, ref recvLen, callback);
|
||||
if (rc != 0 || (response != null && response.IndexOf("fail", StringComparison.OrdinalIgnoreCase) >= 0))
|
||||
{
|
||||
fail++;
|
||||
bFail++;
|
||||
logs.Add($"[TemplateJob {job.Id}] SetEmployee failed. emp={empId} target={target.Machine.MachineIp}");
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} send=FAIL rc={rc}");
|
||||
}
|
||||
else
|
||||
{
|
||||
ok++;
|
||||
bOk++;
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} send=OK");
|
||||
|
||||
if (verifyAfterPush)
|
||||
{
|
||||
string verifyCmd = "GetEmployee(id=\"" + empId + "\")";
|
||||
string verifyResp = "";
|
||||
uint verifyRecvLen = 0;
|
||||
int vrc = Program.test(targetDevInfo, targetDevInfo.Length, verifyCmd, verifyCmd.Length, ref verifyResp, ref verifyRecvLen, callback);
|
||||
bool success = vrc == 0 && verifyResp != null && verifyResp.IndexOf("success", StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
if (success)
|
||||
{
|
||||
verifyOk++;
|
||||
bVerifyOk++;
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} verify=OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
verifyFail++;
|
||||
bVerifyFail++;
|
||||
Program.WriteInternalLog($"[DB_TO_DEVICE] job={job.Id} target={target.Machine.MachineIp} emp={empId} verify=FAIL rc={vrc}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delayMs > 0)
|
||||
{
|
||||
Thread.Sleep(delayMs);
|
||||
}
|
||||
|
||||
swBatch.Stop();
|
||||
logs.Add($"[TemplateTransferBatch] job={job.Id} target_ip={target.Machine.MachineIp} batch={bi + 1}/{batches.Count} attempted={bAttempted} ok={bOk} fail={bFail} verify_ok={bVerifyOk} verify_fail={bVerifyFail} duration_sec={Math.Round(swBatch.Elapsed.TotalSeconds, 1)}");
|
||||
}
|
||||
}
|
||||
|
||||
if (verifyAfterPush)
|
||||
|
|
|
|||
Loading…
Reference in New Issue