Files
admin ed55e77e98
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
add projects
2026-03-17 17:25:08 +03:00

437 lines
16 KiB
C#

using CheckEVS;
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace DahuaDiskChecker
{
class Program
{
static async Task Main(string[] args)
{
string server = string.Empty;
//Console.WriteLine("=== ПРОВЕРКА СОСТОЯНИЯ ДИСКА DAHUA ===");
#if DEBUG
Console.WriteLine("Введи ip-адрес EVS:");
server = Console.ReadLine();
Console.WriteLine("Введи номер диска: (0 - количество неисправных, 1-24 - статус указанного");
int diskNumber = Convert.ToInt32(Console.ReadLine());
#else
// Парсинг аргументов
if (args.Length < 2)
{
await PromoPrint();
//Console.WriteLine("Использование: DahuaDiskChecker.exe <IP> <номер_диска> [пользователь] [пароль]");
//Console.WriteLine("Пример: DahuaDiskChecker.exe 172.16.48.147 10 admin admin");
return;
}
server = args[0];
if (!int.TryParse(args[1], out int diskNumber))
{
//Console.WriteLine("❌ Ошибка: номер диска должен быть числом");
return;
}
#endif
string user = args.Length > 2 ? args[2] : "admin";
string password = args.Length > 3 ? args[3] : "4NUDZhJ7";
try
{
var checker = new DahuaDiskChecker();
string status = await checker.CheckDiskStatusAsync(server, diskNumber, user, password);
// Вывод результата
//Console.WriteLine();
//Console.WriteLine(new string('=', 40));
try
{
Convert.ToInt32(status);
Console.WriteLine(status);
}
catch (Exception)
{
if (status == "NotFound")
{
Console.WriteLine("10");
}
else if (status == "Good")
{
Console.WriteLine("0");
}
else
{
Console.WriteLine("1");
}
}
#if DEBUG
Console.ReadKey();
#endif
//Console.WriteLine(new string('=', 40));
}
catch (Exception ex)
{
Console.WriteLine($"❌ Ошибка: {ex.Message}");
}
}
private static async Task PromoPrint()
{
// ╔ ═ ╦ ╗ ║ ╟ ╤ │ ─ ┷ ╢ ╚ ╝
Console.WriteLine("╔════════════════════════════╤════════════╗");
Console.WriteLine("║ autor: mastankov │ ver: 0.1 ║");
Console.WriteLine("╟────────────────────────────┴────────────╢");
Console.WriteLine("║ Пример: ║");
Console.WriteLine("║ DahuaDiskChecker.exe <IP> <номер_диска> ║");
Console.WriteLine("║ Вернет статус запрошенного диска ║");
Console.WriteLine("║ ║");
Console.WriteLine("║ DahuaDiskChecker.exe <IP> 0 ║");
Console.WriteLine("║ Вернет количество неисправных дисков ║");
Console.WriteLine("║ ║");
Console.WriteLine("║ Нажми Enter, чтобы выйти ║");
Console.WriteLine("╚═════════════════════════════════════════╝");
//Console.ReadKey();
}
}
public class DahuaDiskChecker
{
private readonly HttpClient _httpClient;
public DahuaDiskChecker()
{
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromSeconds(30);
}
// Вычисление MD5 хэша
private string CalculateMD5(string input)
{
using (MD5 md5 = MD5.Create())
{
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach (byte b in hashBytes)
{
sb.Append(b.ToString("X2"));
}
return sb.ToString();
}
}
// Получение сессии
private async Task<string> GetSessionAsync(string server, string user, string password)
{
// 1. Challenge запрос
var challengeRequest = new
{
method = "global.login",
@params = new
{
userName = user,
password = "",
clientType = "Web3.0"
},
id = 1,
session = (string)null
};
string json = JsonSerializer.Serialize(challengeRequest);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync($"http://{server}/RPC2_Login", content);
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync();
using JsonDocument doc = JsonDocument.Parse(responseJson);
var root = doc.RootElement;
if (!root.TryGetProperty("result", out var resultProp) || resultProp.GetBoolean())
throw new Exception("Не удалось получить challenge");
string realm = root.GetProperty("params").GetProperty("realm").GetString();
string random = root.GetProperty("params").GetProperty("random").GetString();
string session = root.GetProperty("session").GetString();
// 2. Вычисление пароля
string pwdHash = CalculateMD5($"{user}:{realm}:{password}");
string passHash = CalculateMD5($"{user}:{random}:{pwdHash}");
// 3. Авторизация
var authRequest = new
{
method = "global.login",
@params = new
{
userName = user,
clientType = "Web3.0",
authorityType = "Default",
passwordType = "Default",
password = passHash
},
id = 2,
session = session
};
json = JsonSerializer.Serialize(authRequest);
content = new StringContent(json, Encoding.UTF8, "application/json");
response = await _httpClient.PostAsync($"http://{server}/RPC2_Login", content);
response.EnsureSuccessStatusCode();
responseJson = await response.Content.ReadAsStringAsync();
using JsonDocument authDoc = JsonDocument.Parse(responseJson);
var authRoot = authDoc.RootElement;
if (!authRoot.TryGetProperty("result", out resultProp) || !resultProp.GetBoolean())
throw new Exception("Ошибка авторизации");
return authRoot.GetProperty("session").GetString();
}
// Получение состояния диска
public async Task<string> CheckDiskStatusAsync(string server, int diskNumber, string user, string password)
{
try
{
// Получаем сессию
string session = await GetSessionAsync(server, user, password);
// Запрос информации о дисках
var diskRequest = new
{
method = "storage.getTankInfo",
@params = (object)null,
id = 270,
session
};
string json = JsonSerializer.Serialize(diskRequest);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync($"http://{server}/RPC2", content);
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync();
var listDisk = Newtonsoft.Json.JsonConvert.DeserializeObject<Disks>(responseJson).@params.tank[0].Device;
if (diskNumber != 0)
{
// Парсим ответ для поиска диска
string diskStatus = ParseDiskInfo(responseJson, diskNumber);
return diskStatus ?? "NotFound";
}
else
{
int countDiskWithError = 0;
for (int i = 0; i < listDisk.Count - 2; i++)
{
if (listDisk[i].PreDiskCheck != "Good" && listDisk[i].PreDiskCheck != "Warn")
countDiskWithError++;
}
return countDiskWithError.ToString();
}
}
catch (HttpRequestException ex)
{
throw new Exception($"Ошибка сети: {ex.Message}");
}
catch (Exception ex)
{
throw new Exception($"Ошибка: {ex.Message}");
}
}
// Парсинг информации о дисках
private string ParseDiskInfo(string jsonResponse, int diskNumber)
{
using JsonDocument doc = JsonDocument.Parse(jsonResponse);
var root = doc.RootElement;
// Проверяем успешность запроса
if (!root.TryGetProperty("result", out var resultProp) || !resultProp.GetBoolean())
return null;
// Ищем диски
if (!root.TryGetProperty("params", out var paramsProp))
return null;
if (!paramsProp.TryGetProperty("tank", out var tanksProp))
return null;
// Перебираем все массивы танков (хранилищ)
foreach (var tank in tanksProp.EnumerateArray())
{
if (!tank.TryGetProperty("Device", out var devicesProp))
continue;
// Перебираем устройства в танке
foreach (var device in devicesProp.EnumerateArray())
{
// Если устройство - строка (как в вашем примере)
if (device.ValueKind == JsonValueKind.String)
{
string deviceStr = device.GetString();
if (deviceStr.Contains($"PhysicNo={diskNumber}"))
{
// Ищем PreDiskCheck
int start = deviceStr.IndexOf("PreDiskCheck=");
if (start == -1) return "Unknown";
start += "PreDiskCheck=".Length;
int end = deviceStr.IndexOf(';', start);
if (end == -1) end = deviceStr.Length;
return deviceStr.Substring(start, end - start).Trim();
}
}
// Если устройство - объект
else if (device.ValueKind == JsonValueKind.Object)
{
// Пробуем получить PhysicNo как строку или число
string physicNo = null;
if (device.TryGetProperty("PhysicNo", out var physicNoProp))
{
if (physicNoProp.ValueKind == JsonValueKind.String)
{
physicNo = physicNoProp.GetString();
}
else if (physicNoProp.ValueKind == JsonValueKind.Number)
{
physicNo = physicNoProp.GetInt32().ToString();
}
}
// Если нашли нужный диск
if (physicNo == diskNumber.ToString())
{
// Получаем статус
if (device.TryGetProperty("PreDiskCheck", out var statusProp))
{
return statusProp.GetString() ?? "Unknown";
}
return "Unknown";
}
}
}
}
return null;
}
}
// Классы для десериализации JSON
public class DahuaResponse<T>
{
[JsonPropertyName("result")]
public bool Result { get; set; }
[JsonPropertyName("session")]
public string Session { get; set; }
[JsonPropertyName("params")]
public T Params { get; set; }
[JsonPropertyName("error")]
public ErrorInfo Error { get; set; }
[JsonPropertyName("id")]
public int Id { get; set; }
}
public class ChallengeData
{
[JsonPropertyName("authorization")]
public string Authorization { get; set; }
[JsonPropertyName("random")]
public string Random { get; set; }
[JsonPropertyName("realm")]
public string Realm { get; set; }
[JsonPropertyName("opaque")]
public string Opaque { get; set; }
}
public class AuthData
{
[JsonPropertyName("keepAliveInterval")]
public int KeepAliveInterval { get; set; }
[JsonPropertyName("isPwdOverdue")]
public bool IsPwdOverdue { get; set; }
}
public class TankInfoData
{
[JsonPropertyName("tank")]
public List<Tank> Tanks { get; set; }
}
public class Tank
{
[JsonPropertyName("Device")]
public List<JsonElement> Devices { get; set; }
[JsonPropertyName("FreeSpace")]
public double FreeSpace { get; set; }
[JsonPropertyName("Level")]
public int Level { get; set; }
[JsonPropertyName("SlotNum")]
public int SlotNum { get; set; }
[JsonPropertyName("TankNo")]
public int TankNo { get; set; }
[JsonPropertyName("Temperature")]
public double Temperature { get; set; }
[JsonPropertyName("TotalSpace")]
public double TotalSpace { get; set; }
}
public class Device
{
[JsonPropertyName("PhysicNo")]
public string PhysicNo { get; set; }
[JsonPropertyName("PreDiskCheck")]
public string PreDiskCheck { get; set; }
[JsonPropertyName("Name")]
public string Name { get; set; }
[JsonPropertyName("SerialNo")]
public string SerialNo { get; set; }
[JsonPropertyName("Temperature")]
public string Temperature { get; set; }
[JsonPropertyName("State")]
public string State { get; set; }
}
public class ErrorInfo
{
[JsonPropertyName("code")]
public int Code { get; set; }
[JsonPropertyName("message")]
public string Message { get; set; }
}
}