chore: HERV 통합 저장소 초기 커밋
- 펌웨어(program), C# 대시보드(TestProgram), 시뮬레이터(Simulator), 프로토콜/문서(Protocol, doc) 전체를 단일 저장소로 통합 - program 폴더의 별도 git 저장소를 제거하고 통합 저장소에 흡수 - 빌드 산출물(program/build, bin/obj, *.o/.elf/.bin/.hex 등) .gitignore 처리 - 사내 Synology NAS Git 원격 연결 예정 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net.Sockets;
|
||||
using ErvProtocol;
|
||||
|
||||
namespace ErvCollector.Storage
|
||||
{
|
||||
// 현장별 활성 소켓 + 최신 상태 보관. 제어 프레임을 해당 현장 EW11 소켓으로 송신.
|
||||
public sealed class SiteHub
|
||||
{
|
||||
readonly ConcurrentDictionary<string, NetworkStream> _sockets = new();
|
||||
readonly ConcurrentDictionary<string, StatusRecord> _last = new();
|
||||
readonly ConcurrentDictionary<string, DateTime> _lastSeenUtc = new();
|
||||
|
||||
public event Action<string>? Log;
|
||||
|
||||
public void SetSocket(string site, NetworkStream s) { _sockets[site] = s; }
|
||||
public void RemoveSocket(string site, NetworkStream s)
|
||||
{
|
||||
// 현재 등록된 것이 이 스트림일 때만 제거(재연결 레이스 방지)
|
||||
if (_sockets.TryGetValue(site, out var cur) && ReferenceEquals(cur, s))
|
||||
_sockets.TryRemove(site, out _);
|
||||
}
|
||||
|
||||
public void SetStatus(string site, StatusRecord rec)
|
||||
{
|
||||
_last[site] = rec;
|
||||
_lastSeenUtc[site] = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public StatusRecord? GetStatus(string site) => _last.TryGetValue(site, out var r) ? r : null;
|
||||
public DateTime LastSeen(string site) => _lastSeenUtc.TryGetValue(site, out var t) ? t : DateTime.MinValue;
|
||||
public bool IsOnline(string site) =>
|
||||
_sockets.ContainsKey(site) && (DateTime.UtcNow - LastSeen(site)) < TimeSpan.FromSeconds(30);
|
||||
|
||||
// 제어 프레임 송신. 성공 true.
|
||||
public bool TrySend(string site, byte[] frame)
|
||||
{
|
||||
if (!_sockets.TryGetValue(site, out var stream))
|
||||
{
|
||||
Log?.Invoke($"[{site}] 제어 실패: 연결 없음");
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
lock (stream) { stream.Write(frame, 0, frame.Length); stream.Flush(); }
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log?.Invoke($"[{site}] 제어 송신 오류: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user