superstar_v2/HeartbeatSender.cs
jasonchenwork d041ff1f80 新增 設定檔
調整 心跳功能
修正 藏鏡人
修正 服務鈴
20250703
2025-07-03 18:15:21 +08:00

157 lines
4.7 KiB
C#

using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualBasic.Devices;
namespace HeartbeatSender;
public class heartbeatSender
{
private readonly HttpClient httpClient = new();
private string token = "";
private string branchName = "";
private string heartbeatDomain = "";
private CancellationTokenSource? cancellationTokenSource;
public heartbeatSender()
{
this.heartbeatDomain = Utils.Env.Get("HeartBeatUrl", "");
// 在建構子中啟動背景心跳任務
_ = Task.Run(() => StartAsync());
}
public async Task StartAsync()
{
cancellationTokenSource = new CancellationTokenSource();
while (!cancellationTokenSource.IsCancellationRequested)
{
try
{
if (string.IsNullOrEmpty(token))
{
bool loginSuccess = await LoginAndGetTokenAsync();
Console.WriteLine(loginSuccess ? "心跳登入成功" : "心跳登入失敗");
}
if (!string.IsNullOrEmpty(token))
{
await SendHeartbeatAsync();
}
await Task.Delay(TimeSpan.FromMinutes(1), cancellationTokenSource.Token);
}
catch (Exception ex)
{
Console.WriteLine($"心跳任務錯誤:{ex.Message}");
await Task.Delay(5000); // 錯誤後延遲再跑
}
}
}
public void Stop()
{
cancellationTokenSource?.Cancel();
Console.WriteLine("心跳任務已停止");
}
public async Task<bool> LoginAndGetTokenAsync()
{
var url = $"{heartbeatDomain.TrimEnd('/')}/api/room/receiveRegister";
var loginPayload = new
{
email = "MachineKTV@gmail.com",
password = "aa147258-"
};
var result = await SendPostAsync<JsonElement>(url, loginPayload);
if (result.ValueKind == JsonValueKind.Object &&
result.TryGetProperty("data", out JsonElement data))
{
token = data.GetProperty("token").GetString()!;
branchName = data.GetProperty("branch_name").GetString()!;
return true;
}
return false;
}
public async Task SendHeartbeatAsync()
{
var url = $"{heartbeatDomain.TrimEnd('/')}/api/room/heartbeat";
string hostName = Dns.GetHostName();
var heartbeatPayload = new
{
branch_name = branchName,
hostname = "PC" + hostName[^3..],
ip = GetLocalIPv4(),
cpu = GetCpuUsage(),
memory = GetTotalMemoryInMB(),
disk = GetDiskTotalSizeInGB()
};
await SendPostAsync<JsonElement>(url, heartbeatPayload, token);
Console.WriteLine($"心跳送出成功: {DateTime.Now:HH:mm:ss}");
}
private async Task<T?> SendPostAsync<T>(string url, object payload, string? bearerToken = null)
{
var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = content
};
if (!string.IsNullOrWhiteSpace(bearerToken))
{
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", bearerToken);
}
var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
string responseJson = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<T>(responseJson);
}
private static string GetLocalIPv4()
{
foreach (var ip in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(ip))
return ip.ToString();
}
return "127.0.0.1";
}
private float GetCpuUsage()
{
using var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
cpuCounter.NextValue();
Thread.Sleep(100);
return cpuCounter.NextValue();
}
private float GetTotalMemoryInMB()
{
var ci = new ComputerInfo();
return (ci.TotalPhysicalMemory - ci.AvailablePhysicalMemory) / 1024f;
}
private float GetDiskTotalSizeInGB(string driveLetter = "C")
{
var drive = new DriveInfo(driveLetter);
return drive.TotalSize / (1024f * 1024f * 1024f);
}
}