157 lines
4.7 KiB
C#
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);
|
|
}
|
|
}
|