DreamineVMS
1.0.0.0
Windows PC의 RTSP·USB 카메라 영상을 HLS로 변환해 원격 CCTV Viewer에 전달하는 데스크톱 에이전트입니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
AgentApiClient.cs
이 파일의 문서화 페이지로 가기
1
using
System.Net.Http;
2
using
System.Net.Http.Json;
3
using
DreamineVMS.Models
;
4
using
Microsoft.Extensions.Configuration;
5
using
Microsoft.Extensions.Logging;
6
7
namespace
DreamineVMS.Services.Agent
;
8
17
public
sealed
class
AgentApiClient
18
{
27
private
readonly HttpClient
_http
;
36
private
readonly ILogger<AgentApiClient>
_logger
;
45
private
readonly List<Uri>
_serverUrls
;
54
private
Uri?
_activeServerUrl
;
55
64
public
string
?
Token
{
get
;
private
set
; }
73
public
string
?
TenantId
{
get
;
private
set
; }
82
public
List<AgentCameraInfo>
Cameras
{
get
;
private
set
; } = [];
83
92
private
string
?
_email
;
101
private
string
?
_password
;
102
127
public
AgentApiClient
(IConfiguration config, ILogger<AgentApiClient> logger)
128
{
129
_logger
= logger;
130
_serverUrls
=
BuildServerCandidates
(config[
"Agent:ServerUrl"
]);
131
_activeServerUrl
=
_serverUrls
.FirstOrDefault();
132
_http
=
new
HttpClient();
133
_email
= config[
"Agent:Email"
];
134
_password
= config[
"Agent:Password"
];
135
}
136
169
public
void
SetCredentials
(
string
serverUrl,
string
email,
string
password)
170
{
171
_email
= email;
172
_password
= password;
173
var newUrls =
BuildServerCandidates
(serverUrl);
174
_serverUrls
.Clear();
175
_serverUrls
.AddRange(newUrls);
176
_activeServerUrl
=
_serverUrls
.FirstOrDefault();
177
Token
=
null
;
// 재로그인 유도
178
}
179
188
public
string
?
Email
=>
_email
;
197
public
string
?
ServerUrl
=>
_activeServerUrl
?.ToString().TrimEnd(
'/'
);
198
215
public
Task<(
bool
Ok,
string
Error)>
LoginWithStoredCredentialsAsync
()
216
{
217
if
(
string
.IsNullOrWhiteSpace(
_email
) ||
string
.IsNullOrWhiteSpace(
_password
))
218
return
Task.FromResult((
false
,
"이메일 또는 비밀번호가 설정되지 않았습니다."
));
219
return
LoginAsync
(
_email
,
_password
);
220
}
221
254
public
async Task<(
bool
Ok,
string
Error)>
LoginAsync
(
string
email,
string
password)
255
{
256
foreach
(Uri serverUrl
in
EnumerateServerUrls
())
257
{
258
try
259
{
260
var resp = await
_http
.PostAsJsonAsync(
261
new
Uri(serverUrl,
"/api/agent/login"
),
262
new
{
Email
= email, Password = password });
263
264
if
(!resp.IsSuccessStatusCode)
265
{
266
_logger
.LogWarning(
"[Agent] 로그인 실패: {Server} responded {StatusCode}."
,
267
serverUrl, (
int
)resp.StatusCode);
268
continue
;
269
}
270
271
var data = await resp.Content.ReadFromJsonAsync<
AgentLoginResponse
>();
272
if
(data is
null
)
273
{
274
_logger
.LogWarning(
"[Agent] 로그인 실패: {Server} returned an empty response."
, serverUrl);
275
continue
;
276
}
277
278
_activeServerUrl
= serverUrl;
279
Token
= data.Token;
280
TenantId
= data.TenantId;
281
Cameras
= data.Cameras ?? [];
282
_logger
.LogInformation(
"[Agent] 중앙 서버 연결: {Server}"
, serverUrl);
283
return
(
true
,
""
);
284
}
285
catch
(Exception ex)
286
{
287
_logger
.LogWarning(ex,
"[Agent] 중앙 서버 연결 실패: {Server}"
, serverUrl);
288
}
289
}
290
291
Token
=
null
;
292
return
(
false
,
"중앙 서버 연결 실패"
);
293
}
294
319
public
async Task<bool>
SyncCamerasAsync
(IEnumerable<AgentCameraInfo> cameras)
320
{
321
if
(
Token
is
null
)
return
false
;
322
try
323
{
324
Uri serverUrl =
GetActiveServerUrl
();
325
var payload =
new
326
{
327
Token
,
328
Cameras
= cameras.Select(c =>
new
329
{
330
c.Id, c.Name, c.Host, c.RtspUrl, c.AutoReconnect, c.IsPublic
331
})
332
};
333
var resp = await
_http
.PostAsJsonAsync(
new
Uri(serverUrl,
"/api/agent/sync-cameras"
), payload);
334
if
(!resp.IsSuccessStatusCode)
335
{
336
_logger
.LogWarning(
"[Agent] 카메라 동기화 실패: {Server} responded {StatusCode}."
,
337
serverUrl, (
int
)resp.StatusCode);
338
}
339
340
return
resp.IsSuccessStatusCode;
341
}
342
catch
(Exception ex)
343
{
344
_logger
.LogWarning(ex,
"[Agent] 카메라 동기화 중 오류"
);
345
return
false
;
346
}
347
}
348
389
public
async Task<bool>
PushSegmentAsync
(
string
cameraId,
string
filename,
byte
[] data)
390
{
391
if
(
Token
is
null
)
return
false
;
392
try
393
{
394
Uri serverUrl =
GetActiveServerUrl
();
395
using
var content =
new
ByteArrayContent(data);
396
var resp = await
_http
.PostAsync(
397
new
Uri(serverUrl, $
"/api/agent/hls/{Token}/{cameraId}/{filename}"
),
398
content);
399
400
if
(resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
401
{
402
Token
=
null
;
// 재로그인 트리거
403
_logger
.LogWarning(
"[Agent] 세그먼트 업로드 인증 만료: {CameraId}/{Filename}"
, cameraId, filename);
404
return
false
;
405
}
406
407
if
(!resp.IsSuccessStatusCode)
408
{
409
_logger
.LogWarning(
"[Agent] 세그먼트 업로드 실패: {CameraId}/{Filename} responded {StatusCode}."
,
410
cameraId, filename, (
int
)resp.StatusCode);
411
}
412
413
return
resp.IsSuccessStatusCode;
414
}
415
catch
(Exception ex)
416
{
417
Token
=
null
;
// 서버 포트가 바뀌었거나 재시작된 경우 다음 루프에서 재로그인합니다.
418
_logger
.LogWarning(ex,
"[Agent] 세그먼트 업로드 중 오류: {CameraId}/{Filename}"
, cameraId, filename);
419
return
false
;
420
}
421
}
422
431
public
void
ClearToken
() =>
Token
=
null
;
432
449
private
Uri
GetActiveServerUrl
()
450
{
451
return
_activeServerUrl
??
_serverUrls
.First();
452
}
453
470
private
IEnumerable<Uri>
EnumerateServerUrls
()
471
{
472
if
(
_activeServerUrl
is not
null
)
473
{
474
yield
return
_activeServerUrl
;
475
}
476
477
foreach
(Uri serverUrl
in
_serverUrls
)
478
{
479
if
(
_activeServerUrl
is not
null
&& serverUrl ==
_activeServerUrl
)
480
{
481
continue
;
482
}
483
484
yield
return
serverUrl;
485
}
486
}
487
512
private
static
List<Uri>
BuildServerCandidates
(
string
? configuredUrl)
513
{
514
var candidates =
new
List<string>();
515
Add(configuredUrl);
516
Add(
"http://localhost:6080"
);
517
Add(
"https://localhost:6443"
);
518
519
return
candidates
520
.Select(item =>
new
Uri(item.EndsWith(
'/'
) ? item : item +
"/"
))
521
.Distinct()
522
.ToList();
523
524
#pragma warning disable CS1587
543
void
Add(
string
? url)
544
{
545
if
(
string
.IsNullOrWhiteSpace(url))
546
{
547
return
;
548
}
549
550
candidates.Add(url.Trim());
551
}
552
#pragma warning restore CS1587
553
}
554
}
555
564
public
sealed
class
AgentCameraInfo
565
{
574
public
string
Id
{
get
;
set
; } =
""
;
583
public
string
Name
{
get
;
set
; } =
""
;
592
public
string
Host
{
get
;
set
; } =
""
;
601
public
string
RtspUrl
{
get
;
set
; } =
""
;
610
public
bool
AutoReconnect
{
get
;
set
; }
619
public
bool
IsPublic
{
get
;
set
; }
620
}
621
630
file
sealed
class
AgentLoginResponse
631
{
640
public
string
Token
{
get
;
set
; } =
""
;
649
public
string
TenantId
{
get
;
set
; } =
""
;
658
public
List<AgentCameraInfo>?
Cameras
{
get
;
set
; }
659
}
DreamineVMS.Models
Definition
CameraConnectionState.cs:1
DreamineVMS.Services.Agent
Definition
AgentApiClient.cs:7
DreamineVMS.Services.Agent.AgentApiClient.AgentApiClient
AgentApiClient(IConfiguration config, ILogger< AgentApiClient > logger)
Definition
AgentApiClient.cs:127
DreamineVMS.Services.Agent.AgentApiClient.ClearToken
void ClearToken()
Definition
AgentApiClient.cs:431
DreamineVMS.Services.Agent.AgentApiClient._logger
readonly ILogger< AgentApiClient > _logger
Definition
AgentApiClient.cs:36
DreamineVMS.Services.Agent.AgentApiClient.BuildServerCandidates
static List< Uri > BuildServerCandidates(string? configuredUrl)
Definition
AgentApiClient.cs:512
DreamineVMS.Services.Agent.AgentApiClient._serverUrls
readonly List< Uri > _serverUrls
Definition
AgentApiClient.cs:45
DreamineVMS.Services.Agent.AgentApiClient.Email
string? Email
Definition
AgentApiClient.cs:188
DreamineVMS.Services.Agent.AgentApiClient.ServerUrl
string? ServerUrl
Definition
AgentApiClient.cs:197
DreamineVMS.Services.Agent.AgentApiClient.SetCredentials
void SetCredentials(string serverUrl, string email, string password)
Definition
AgentApiClient.cs:169
DreamineVMS.Services.Agent.AgentApiClient.TenantId
string? TenantId
Definition
AgentApiClient.cs:73
DreamineVMS.Services.Agent.AgentApiClient.GetActiveServerUrl
Uri GetActiveServerUrl()
Definition
AgentApiClient.cs:449
DreamineVMS.Services.Agent.AgentApiClient.PushSegmentAsync
async Task< bool > PushSegmentAsync(string cameraId, string filename, byte[] data)
Definition
AgentApiClient.cs:389
DreamineVMS.Services.Agent.AgentApiClient.LoginWithStoredCredentialsAsync
Task<(bool Ok, string Error)> LoginWithStoredCredentialsAsync()
Definition
AgentApiClient.cs:215
DreamineVMS.Services.Agent.AgentApiClient._activeServerUrl
Uri? _activeServerUrl
Definition
AgentApiClient.cs:54
DreamineVMS.Services.Agent.AgentApiClient.EnumerateServerUrls
IEnumerable< Uri > EnumerateServerUrls()
Definition
AgentApiClient.cs:470
DreamineVMS.Services.Agent.AgentApiClient._http
readonly HttpClient _http
Definition
AgentApiClient.cs:27
DreamineVMS.Services.Agent.AgentApiClient.Cameras
List< AgentCameraInfo > Cameras
Definition
AgentApiClient.cs:82
DreamineVMS.Services.Agent.AgentApiClient.SyncCamerasAsync
async Task< bool > SyncCamerasAsync(IEnumerable< AgentCameraInfo > cameras)
Definition
AgentApiClient.cs:319
DreamineVMS.Services.Agent.AgentApiClient._password
string? _password
Definition
AgentApiClient.cs:101
DreamineVMS.Services.Agent.AgentApiClient._email
string? _email
Definition
AgentApiClient.cs:92
DreamineVMS.Services.Agent.AgentApiClient.Token
string? Token
Definition
AgentApiClient.cs:64
DreamineVMS.Services.Agent.AgentApiClient.LoginAsync
async Task<(bool Ok, string Error)> LoginAsync(string email, string password)
Definition
AgentApiClient.cs:254
DreamineVMS.Services.Agent.AgentCameraInfo
Definition
AgentApiClient.cs:565
DreamineVMS.Services.Agent.AgentCameraInfo.AutoReconnect
bool AutoReconnect
Definition
AgentApiClient.cs:610
DreamineVMS.Services.Agent.AgentCameraInfo.Name
string Name
Definition
AgentApiClient.cs:583
DreamineVMS.Services.Agent.AgentCameraInfo.IsPublic
bool IsPublic
Definition
AgentApiClient.cs:619
DreamineVMS.Services.Agent.AgentCameraInfo.RtspUrl
string RtspUrl
Definition
AgentApiClient.cs:601
DreamineVMS.Services.Agent.AgentCameraInfo.Id
string Id
Definition
AgentApiClient.cs:574
DreamineVMS.Services.Agent.AgentCameraInfo.Host
string Host
Definition
AgentApiClient.cs:592
DreamineVMS.Services.Agent.AgentLoginResponse
Definition
AgentApiClient.cs:631
DreamineVMS.Services.Agent.AgentLoginResponse.TenantId
string TenantId
Definition
AgentApiClient.cs:649
DreamineVMS.Services.Agent.AgentLoginResponse.Token
string Token
Definition
AgentApiClient.cs:640
DreamineVMS.Services.Agent.AgentLoginResponse.Cameras
List< AgentCameraInfo >? Cameras
Definition
AgentApiClient.cs:658
Services
Agent
AgentApiClient.cs
다음에 의해 생성됨 :
1.17.0