Compare commits
13 Commits
e37b03f072
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 90cbc7c506 | |||
| 794fc621ff | |||
| d426ab1e78 | |||
| 6ddc6be910 | |||
| f3c4c55c55 | |||
| c94e07d6c0 | |||
| eeaf87a07e | |||
| 04b5303dac | |||
| 73a4e0b5bb | |||
| 57aebb7b1c | |||
| 76d090b744 | |||
| cb931df1b8 | |||
| c2c0c8d1ad |
@@ -6,12 +6,15 @@ namespace DahuaIPCRename
|
||||
{
|
||||
public static Dictionary<string, string> listIPC = new Dictionary<string, string>
|
||||
{
|
||||
{"172.22.10.221","Домофон|Глав.вход"},
|
||||
{"172.22.10.222","Домофон|Линкор"},
|
||||
{"172.22.10.223","Домофон|НЛК-1"},
|
||||
{"172.22.10.224","Домофон|НЛК-2"},
|
||||
{"172.22.10.225","Домофон|Ленмикс"},
|
||||
{"172.22.10.226","Домофон|Карбон"}
|
||||
{"172.22.10.122","Этаж 2|Пом. 247"},
|
||||
{"172.22.10.123","Этаж 2|Пом. 248-4"},
|
||||
{"172.22.10.124","Этаж 2|Пом. 248-5"},
|
||||
{"172.22.10.125","Этаж 2|Пом. 248-2"},
|
||||
{"172.22.10.126","Этаж 2|Пом. 248-6"},
|
||||
{"172.22.10.127","Этаж 2|Пом. 248-3"},
|
||||
{"172.22.10.128","Этаж 2|Пом. 273-1"},
|
||||
{"172.22.10.129","Этаж 2|Пом. 268-1"},
|
||||
{"172.22.10.130","Этаж 2|Пом. 273-2"}
|
||||
};
|
||||
|
||||
static async Task Main(string[] args)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Emgu.CV" Version="4.13.0.5924" />
|
||||
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.13.0.5924" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.2.11" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.9" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="10.0.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="haarcascade_frontalface_default.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,7 @@
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace FaceRecognitionApp.Hubs;
|
||||
|
||||
public class FaceHub : Hub
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace FaceRecognitionApp.Models;
|
||||
|
||||
public class Employee
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Department { get; set; }
|
||||
public byte[] FaceDescriptor { get; set; } = Array.Empty<byte>();
|
||||
public byte[]? Photo { get; set; }
|
||||
}
|
||||
|
||||
public class DetectedFace
|
||||
{
|
||||
public byte[] ImageData { get; set; } = Array.Empty<byte>();
|
||||
public bool IsRecognized { get; set; }
|
||||
public Employee? MatchedEmployee { get; set; }
|
||||
public double Confidence { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using FaceRecognitionApp.Hubs;
|
||||
using FaceRecognitionApp.Services;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Регистрация сервисов
|
||||
builder.Services.AddSingleton<DatabaseService>();
|
||||
builder.Services.AddSingleton<FaceRecognitionService>();
|
||||
builder.Services.AddSignalR();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// 1. Включаем поиск файлов по умолчанию (index.html, default.html и т.д.)
|
||||
app.UseDefaultFiles();
|
||||
|
||||
// 2. Включаем раздачу статических файлов (css, js, картинки)
|
||||
app.UseStaticFiles();
|
||||
|
||||
// 3. Подключаем SignalR хаб
|
||||
app.MapHub<FaceHub>("/faceHub");
|
||||
|
||||
// Инициализация камеры и распознавания
|
||||
var db = app.Services.GetRequiredService<DatabaseService>();
|
||||
var faceService = app.Services.GetRequiredService<FaceRecognitionService>();
|
||||
|
||||
// URL камеры (замените на свой или используйте тестовый видеофайл)
|
||||
var cameraUrl = Environment.GetEnvironmentVariable("CAMERA_URL") ?? "rtsp://admin:4NUDZhJ7@172.22.10.101:554/cam/realmonitor?channel=1&subtype=1";
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"Connecting to camera: {cameraUrl}...");
|
||||
var camera = new CameraService(cameraUrl, faceService, async (face) => {
|
||||
var hub = app.Services.GetRequiredService<IHubContext<FaceHub>>();
|
||||
await hub.Clients.All.SendAsync("NewFace", new
|
||||
{
|
||||
image = Convert.ToBase64String(face.ImageData),
|
||||
isRecognized = face.IsRecognized,
|
||||
name = face.MatchedEmployee?.Name ?? "Unknown"
|
||||
});
|
||||
});
|
||||
camera.Start();
|
||||
Console.WriteLine("✅ Camera service started.");
|
||||
|
||||
// Корректное завершение работы камеры при остановке приложения
|
||||
app.Lifetime.ApplicationStopping.Register(() => {
|
||||
Console.WriteLine("Shutting down camera...");
|
||||
camera.Dispose();
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"⚠️ Camera Error: {ex.Message}");
|
||||
Console.WriteLine("Application will run without camera monitoring.");
|
||||
}
|
||||
|
||||
Console.WriteLine("🚀 Application is ready. Open http://localhost:5290 in your browser.");
|
||||
app.Run();
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:43065",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5290",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
using Emgu.CV;
|
||||
using FaceRecognitionApp.Models;
|
||||
|
||||
namespace FaceRecognitionApp.Services;
|
||||
|
||||
public class CameraService : IDisposable
|
||||
{
|
||||
private VideoCapture? _capture;
|
||||
private readonly FaceRecognitionService _recognition;
|
||||
private readonly Action<DetectedFace> _onDetected;
|
||||
private CancellationTokenSource? _cts;
|
||||
private Task? _task;
|
||||
private DateTime _lastTime = DateTime.MinValue;
|
||||
private bool _isDisposed = false;
|
||||
|
||||
public CameraService(string url, FaceRecognitionService recognition, Action<DetectedFace> onDetected)
|
||||
{
|
||||
_recognition = recognition;
|
||||
_onDetected = onDetected;
|
||||
|
||||
Console.WriteLine($"Initializing camera with URL: {url}");
|
||||
_capture = new VideoCapture(url);
|
||||
|
||||
// Даем камере время на инициализацию потока
|
||||
Thread.Sleep(1000);
|
||||
|
||||
if (!_capture.IsOpened)
|
||||
throw new Exception("Camera failed to open. Check URL and network connection.");
|
||||
|
||||
Console.WriteLine("Camera hardware initialized.");
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
_task = Task.Run(() => Loop(_cts.Token));
|
||||
Console.WriteLine("Camera processing loop started.");
|
||||
}
|
||||
|
||||
private async Task Loop(CancellationToken token)
|
||||
{
|
||||
Console.WriteLine("🎥 Frame processing loop active...");
|
||||
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var frame = new Mat();
|
||||
|
||||
// Читаем кадр с таймаутом
|
||||
if (_capture!.Read(frame))
|
||||
{
|
||||
if (!frame.IsEmpty && frame.Width > 0 && frame.Height > 0)
|
||||
{
|
||||
var face = _recognition.ProcessFrame(frame);
|
||||
|
||||
if (face != null)
|
||||
{
|
||||
// Лимит частоты отправок (не чаще раза в 2 секунды)
|
||||
if ((DateTime.Now - _lastTime).TotalMilliseconds > 2000)
|
||||
{
|
||||
_lastTime = DateTime.Now;
|
||||
_onDetected(face);
|
||||
|
||||
string status = face.IsRecognized
|
||||
? $"✅ Recognized: {face.MatchedEmployee?.Name}"
|
||||
: "❌ Unknown face";
|
||||
|
||||
Console.WriteLine($"{DateTime.Now:HH:mm:ss} - {status}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Если Read вернул false, возможно потеря связи
|
||||
Console.WriteLine("⚠️ Failed to read frame, retrying...");
|
||||
await Task.Delay(500, token);
|
||||
}
|
||||
|
||||
// Небольшая задержка, чтобы не грузить процессор на 100%
|
||||
await Task.Delay(50, token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Это нормальная ситуация при остановке
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"⚠️ Error in camera loop: {ex.Message}");
|
||||
await Task.Delay(1000, token);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("🛑 Camera loop finished.");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (_cts == null) return;
|
||||
|
||||
Console.WriteLine("Stopping camera service...");
|
||||
_cts.Cancel();
|
||||
|
||||
try
|
||||
{
|
||||
// Ждем завершения задачи, но не бесконечно
|
||||
if (_task != null)
|
||||
{
|
||||
_task.Wait(TimeSpan.FromSeconds(5));
|
||||
}
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
// Игнорируем ошибки отмены задачи
|
||||
foreach (var inner in ex.InnerExceptions)
|
||||
{
|
||||
if (!(inner is TaskCanceledException || inner is OperationCanceledException))
|
||||
{
|
||||
Console.WriteLine($"Unexpected error during stop: {inner.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error stopping task: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
Stop();
|
||||
_capture?.Dispose();
|
||||
_cts?.Dispose();
|
||||
_isDisposed = true;
|
||||
|
||||
Console.WriteLine("Camera resources released.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using FaceRecognitionApp.Models;
|
||||
|
||||
namespace FaceRecognitionApp.Services;
|
||||
|
||||
public class DatabaseService
|
||||
{
|
||||
private readonly string _connectionString = "Data Source=faces.db";
|
||||
|
||||
public DatabaseService()
|
||||
{
|
||||
InitializeDatabase();
|
||||
}
|
||||
|
||||
private void InitializeDatabase()
|
||||
{
|
||||
using var connection = new SqliteConnection(_connectionString);
|
||||
connection.Open();
|
||||
var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = @"
|
||||
CREATE TABLE IF NOT EXISTS Employees (
|
||||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
Name TEXT NOT NULL,
|
||||
Department TEXT,
|
||||
FaceDescriptor BLOB,
|
||||
Photo BLOB
|
||||
)";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public void AddEmployee(string name, string? dept, byte[] descriptor, byte[] photo)
|
||||
{
|
||||
using var connection = new SqliteConnection(_connectionString);
|
||||
connection.Open();
|
||||
var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = "INSERT INTO Employees (Name, Department, FaceDescriptor, Photo) VALUES (@n, @d, @desc, @p)";
|
||||
cmd.Parameters.AddWithValue("@n", name);
|
||||
cmd.Parameters.AddWithValue("@d", (object?)dept ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("@desc", descriptor);
|
||||
cmd.Parameters.AddWithValue("@p", photo);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public List<Employee> GetAllEmployees()
|
||||
{
|
||||
var list = new List<Employee>();
|
||||
using var connection = new SqliteConnection(_connectionString);
|
||||
connection.Open();
|
||||
var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = "SELECT * FROM Employees";
|
||||
using var reader = cmd.ExecuteReader();
|
||||
while (reader.Read())
|
||||
{
|
||||
list.Add(new Employee
|
||||
{
|
||||
Id = reader.GetInt32(0),
|
||||
Name = reader.GetString(1),
|
||||
Department = reader.IsDBNull(2) ? null : reader.GetString(2),
|
||||
FaceDescriptor = (byte[])reader[3],
|
||||
Photo = reader.IsDBNull(4) ? null : (byte[])reader[4]
|
||||
});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Face;
|
||||
using Emgu.CV.Structure;
|
||||
using Emgu.CV.Util;
|
||||
using FaceRecognitionApp.Models;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FaceRecognitionApp.Services;
|
||||
|
||||
public class FaceRecognitionService : IDisposable
|
||||
{
|
||||
private readonly LBPHFaceRecognizer _recognizer;
|
||||
private readonly CascadeClassifier _cascade;
|
||||
private readonly DatabaseService _db;
|
||||
private List<Employee> _employees = new();
|
||||
private bool _isTrained = false;
|
||||
|
||||
// Коэффициент уменьшения кадра для ускорения поиска
|
||||
private const double ResizeScale = 0.5;
|
||||
private const int OriginalMinSize = 30;
|
||||
private readonly Size _scaledMinSize;
|
||||
|
||||
public FaceRecognitionService(DatabaseService db)
|
||||
{
|
||||
_db = db;
|
||||
var cascadePath = Path.Combine(AppContext.BaseDirectory, "haarcascade_frontalface_default.xml");
|
||||
if (!File.Exists(cascadePath))
|
||||
throw new FileNotFoundException($"Cascade file missing at: {cascadePath}");
|
||||
|
||||
_cascade = new CascadeClassifier(cascadePath);
|
||||
_recognizer = new LBPHFaceRecognizer(1, 8, 8, 8, 80.0);
|
||||
|
||||
// Вычисляем минимальный размер лица для уменьшенного кадра
|
||||
int scaledMin = (int)(OriginalMinSize * ResizeScale);
|
||||
_scaledMinSize = new Size(Math.Max(scaledMin, 10), Math.Max(scaledMin, 10));
|
||||
|
||||
TrainModel();
|
||||
}
|
||||
|
||||
private void TrainModel()
|
||||
{
|
||||
_employees = _db.GetAllEmployees();
|
||||
if (!_employees.Any()) return;
|
||||
|
||||
using var images = new VectorOfMat();
|
||||
using var labels = new VectorOfInt();
|
||||
|
||||
foreach (var emp in _employees)
|
||||
{
|
||||
if (emp.Photo == null || emp.Photo.Length == 0) continue;
|
||||
|
||||
try
|
||||
{
|
||||
using var ms = new MemoryStream(emp.Photo);
|
||||
using var bmp = new Bitmap(ms);
|
||||
using var mat = BitmapToMat(bmp);
|
||||
using var gray = new Mat();
|
||||
|
||||
CvInvoke.CvtColor(mat, gray, ColorConversion.Bgr2Gray);
|
||||
|
||||
// Ищем лицо на фото сотрудника для обрезки
|
||||
var rects = _cascade.DetectMultiScale(gray, 1.1, 5, new Size(30, 30));
|
||||
|
||||
if (rects.Length > 0)
|
||||
{
|
||||
using var faceMat = new Mat(gray, rects[0]);
|
||||
using var resized = new Mat();
|
||||
CvInvoke.Resize(faceMat, resized, new Size(100, 100));
|
||||
|
||||
images.Push(resized);
|
||||
labels.Push(new int[] { emp.Id });
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Training error for {emp.Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
if (images.Size > 0)
|
||||
{
|
||||
_recognizer.Train(images, labels);
|
||||
_isTrained = true;
|
||||
Console.WriteLine($"✅ Trained on {images.Size} faces.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("⚠️ No valid faces found for training.");
|
||||
}
|
||||
}
|
||||
|
||||
public DetectedFace? ProcessFrame(Mat frame)
|
||||
{
|
||||
if (frame == null || frame.IsEmpty) return null;
|
||||
|
||||
// === УСКОРЕНИЕ: Уменьшаем кадр для поиска лиц ===
|
||||
using var smallFrame = new Mat();
|
||||
CvInvoke.Resize(frame, smallFrame, new Size(), ResizeScale, ResizeScale, Inter.Linear);
|
||||
|
||||
using var gray = new Mat();
|
||||
CvInvoke.CvtColor(smallFrame, gray, ColorConversion.Bgr2Gray);
|
||||
|
||||
// Ищем лица на уменьшенном кадре
|
||||
var rects = _cascade.DetectMultiScale(gray, 1.1, 5, _scaledMinSize);
|
||||
|
||||
if (rects.Length == 0)
|
||||
return null;
|
||||
|
||||
var smallRect = rects[0];
|
||||
|
||||
// === ВОССТАНОВЛЕНИЕ координат к оригинальному размеру ===
|
||||
int invScale = (int)(1.0 / ResizeScale);
|
||||
var originalRect = new Rectangle(
|
||||
smallRect.X * invScale,
|
||||
smallRect.Y * invScale,
|
||||
smallRect.Width * invScale,
|
||||
smallRect.Height * invScale
|
||||
);
|
||||
|
||||
// Проверка границ по оригинальному кадру
|
||||
if (originalRect.X < 0 || originalRect.Y < 0 ||
|
||||
originalRect.Right > frame.Width || originalRect.Bottom > frame.Height)
|
||||
return null;
|
||||
|
||||
// Вырезаем лицо из ОРИГИНАЛЬНОГО кадра (лучшее качество для распознавания)
|
||||
using var faceMat = new Mat(frame, originalRect);
|
||||
using var faceGray = new Mat();
|
||||
CvInvoke.CvtColor(faceMat, faceGray, ColorConversion.Bgr2Gray);
|
||||
|
||||
using var resized = new Mat();
|
||||
CvInvoke.Resize(faceGray, resized, new Size(100, 100));
|
||||
|
||||
var result = new DetectedFace();
|
||||
|
||||
if (_isTrained)
|
||||
{
|
||||
try
|
||||
{
|
||||
var prediction = _recognizer.Predict(resized);
|
||||
|
||||
int label = prediction.Label;
|
||||
double confidence = prediction.Distance;
|
||||
|
||||
if (label != -1 && confidence < 80)
|
||||
{
|
||||
result.IsRecognized = true;
|
||||
result.MatchedEmployee = _employees.FirstOrDefault(e => e.Id == label);
|
||||
result.Confidence = confidence;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Prediction error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Конвертация в JPEG для веб-интерфейса
|
||||
using var ms = new MemoryStream();
|
||||
using var bmp = MatToBitmap(resized);
|
||||
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
|
||||
result.ImageData = ms.ToArray();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Безопасная конвертация Bitmap → Mat через промежуточный буфер
|
||||
/// </summary>
|
||||
private static Mat BitmapToMat(Bitmap bitmap)
|
||||
{
|
||||
var mat = new Mat(bitmap.Height, bitmap.Width, DepthType.Cv8U, 3);
|
||||
|
||||
var data = bitmap.LockBits(
|
||||
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
System.Drawing.Imaging.ImageLockMode.ReadOnly,
|
||||
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
|
||||
try
|
||||
{
|
||||
int length = Math.Abs(data.Stride) * bitmap.Height;
|
||||
byte[] buffer = new byte[length];
|
||||
Marshal.Copy(data.Scan0, buffer, 0, length);
|
||||
Marshal.Copy(buffer, 0, mat.DataPointer, length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.UnlockBits(data);
|
||||
}
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Безопасная конвертация Mat → Bitmap через промежуточный буфер
|
||||
/// </summary>
|
||||
private static Bitmap MatToBitmap(Mat mat)
|
||||
{
|
||||
var colorMat = new Mat();
|
||||
if (mat.NumberOfChannels == 1)
|
||||
CvInvoke.CvtColor(mat, colorMat, ColorConversion.Gray2Bgr);
|
||||
else
|
||||
mat.CopyTo(colorMat);
|
||||
|
||||
var bmp = new Bitmap(colorMat.Width, colorMat.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
|
||||
var data = bmp.LockBits(
|
||||
new Rectangle(0, 0, bmp.Width, bmp.Height),
|
||||
System.Drawing.Imaging.ImageLockMode.WriteOnly,
|
||||
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
|
||||
try
|
||||
{
|
||||
int length = Math.Abs(data.Stride) * colorMat.Height;
|
||||
byte[] buffer = new byte[length];
|
||||
Marshal.Copy(colorMat.DataPointer, buffer, 0, length);
|
||||
Marshal.Copy(buffer, 0, data.Scan0, length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
bmp.UnlockBits(data);
|
||||
colorMat.Dispose();
|
||||
}
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cascade?.Dispose();
|
||||
_recognizer?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Camera": {
|
||||
"Url": "rtsp://admin:4NUDZhJ7@172.22.10.101:554/cam/realmonitor?channel=1&subtype=0"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Face Recognition</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
background: #222;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#gallery {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #333;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
border: 3px solid red;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.known img {
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-top: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 0.8em;
|
||||
color: #aaa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Live Face Detection</h1>
|
||||
<div id="gallery"></div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.0/signalr.min.js"></script>
|
||||
<script>
|
||||
const connection = new signalR.HubConnectionBuilder().withUrl("/faceHub").build();
|
||||
|
||||
connection.on("NewFace", (data) => {
|
||||
const div = document.createElement('div');
|
||||
div.className = data.isRecognized ? 'card known' : 'card';
|
||||
div.innerHTML = `
|
||||
<img src="data:image/jpeg;base64,${data.image}" />
|
||||
<div class="name">${data.isRecognized ? data.name : 'Unknown'}</div>
|
||||
<div class="time">${new Date().toLocaleTimeString()}</div>
|
||||
`;
|
||||
const gallery = document.getElementById('gallery');
|
||||
gallery.insertBefore(div, gallery.firstChild);
|
||||
if (gallery.children.length > 20) gallery.lastChild.remove();
|
||||
});
|
||||
|
||||
connection.start().catch(console.error);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace GenerateYAMLforZabbix
|
||||
{
|
||||
@@ -16,14 +17,16 @@ namespace GenerateYAMLforZabbix
|
||||
foreach (var host in list)
|
||||
{
|
||||
//var act4 = host[0].Split(".")[3];
|
||||
var text = $""+
|
||||
var text = $"" +
|
||||
$" - host: {host[0]}\r\n" +
|
||||
$" name: (СПб){host[1]}\r\n" +
|
||||
$" name: (ВНК54){host[1]}\r\n" +
|
||||
$" templates:\r\n" +
|
||||
$" - name: 'SEC Dahua Camera SNMP'\r\n" +
|
||||
$" groups:\r\n" +
|
||||
$" - name: dahua.cam.spb\r\n" +
|
||||
$" - name: dahua.cam.vnk.54\r\n" +
|
||||
$" interfaces:\r\n" +
|
||||
$" - ip: {host[0]}\r\n" +
|
||||
$" interface_ref: if2\r\n" +
|
||||
$" - type: SNMP\r\n" +
|
||||
$" ip: {host[0]}\r\n" +
|
||||
$" port: '161'\r\n" +
|
||||
@@ -36,4 +39,20 @@ namespace GenerateYAMLforZabbix
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// - host: 172.16.54.16
|
||||
//name: 'Антресоль 3 1-56-T'
|
||||
// templates:
|
||||
//-name: 'SEC Dahua Camera SNMP'
|
||||
// groups:
|
||||
//-name: dahua.cam.vnk.54
|
||||
// interfaces:
|
||||
//-ip: 172.16.54.16
|
||||
// interface_ref: if2
|
||||
// - type: SNMP
|
||||
// ip: 172.16.54.16
|
||||
// port: '161'
|
||||
// details:
|
||||
//community: '{$SNMP_COMMUNITY}'
|
||||
// interface_ref: if1
|
||||
// inventory_mode: DISABLED
|
||||
@@ -1,6 +1,6 @@
|
||||
zabbix_export:
|
||||
version: '7.0'
|
||||
host_groups:
|
||||
- uuid: 1c44fc80770242e5a82b2e06b9b368b2
|
||||
name: dahua.cam.spb
|
||||
- uuid: 08a2bf5f5f8c475cbb56ef0c70354a93
|
||||
name: dahua.cam.vnk.54
|
||||
hosts:
|
||||
|
||||
@@ -1,42 +1,32 @@
|
||||
172.22.10.51;Пом.545-2
|
||||
172.22.10.52;Пом.519-1
|
||||
172.22.10.53;Пом.511-1
|
||||
172.22.10.54;Пом.517-2
|
||||
172.22.10.55;Эвак. Выход-3
|
||||
172.22.10.56;Пом.545-коридор
|
||||
172.22.10.57;Ресепшн-1
|
||||
172.22.10.58;Пом.545-3
|
||||
172.22.10.59;Пом.521-3
|
||||
172.22.10.60;Пом.535 к лифтам
|
||||
172.22.10.61;Пом.515-2
|
||||
172.22.10.62;Пом.511-2
|
||||
172.22.10.63;Пом.517-1
|
||||
172.22.10.64;Пом.521-1
|
||||
172.22.10.65;Пом.535-коридор
|
||||
172.22.10.66;Пом.526-столовая
|
||||
172.22.10.67;Пом.545-4
|
||||
172.22.10.68;Пом.532-2
|
||||
172.22.10.69;Пом.515-1
|
||||
172.22.10.70;Пом.535-1
|
||||
172.22.10.71;Эвак. Выход-2
|
||||
172.22.10.72;Пом.545-1
|
||||
172.22.10.73;Ресепшн-2
|
||||
172.22.10.74;Пом.521-2
|
||||
172.22.10.93;Пом.319-столовая
|
||||
172.22.10.94;Пом.313-1
|
||||
172.22.10.95;Пом.321-1
|
||||
172.22.10.96;Коридор от лифт. холла
|
||||
172.22.10.97;Пом.321-2
|
||||
172.22.10.98;Коридор к лифт. холлу
|
||||
172.22.10.99;Пом.313-2
|
||||
172.22.10.100;Пом.323-2
|
||||
172.22.10.101;Пом.323-1
|
||||
172.22.10.102;Эвак. Выход
|
||||
172.22.10.103;Кроссовая
|
||||
172.22.10.104;Пом.304-1
|
||||
172.22.10.105;Пом.304-2
|
||||
172.22.10.106;Пом.312
|
||||
172.22.10.107;Пом.237
|
||||
172.22.10.108;Пом.519-2
|
||||
172.22.10.109;Пом.244-1
|
||||
172.22.10.110;Пом.244-2
|
||||
172.16.54.18;Ворота 35
|
||||
172.16.54.20;Ворота 36
|
||||
172.16.54.21;Ворота 31
|
||||
172.16.54.22;Ворота 32
|
||||
172.16.54.23;Ворота 33
|
||||
172.16.54.24;Ворота 34
|
||||
172.16.54.28;Ворота 16
|
||||
172.16.54.29;Ворота 26
|
||||
172.16.54.30;Ворота 20
|
||||
172.16.54.31;Ворота 22
|
||||
172.16.54.32;Ворота 18
|
||||
172.16.54.33;Ворота 21
|
||||
172.16.54.34;Ворота 24
|
||||
172.16.54.35;Ворота 27
|
||||
172.16.54.36;Ворота 29
|
||||
172.16.54.37;Ворота 25
|
||||
172.16.54.38;Ворота 23
|
||||
172.16.54.39;Ворота 15
|
||||
172.16.54.40;Ворота 17
|
||||
172.16.54.41;Ворота 37
|
||||
172.16.54.42;Ворота 19
|
||||
172.16.54.43;Ворота 28
|
||||
172.16.54.45;Подмезанин 1 Зона 2
|
||||
172.16.54.46;Подмезанин 1 Зона 5
|
||||
172.16.54.47;Подмезанин 1 Зона 3
|
||||
172.16.54.48;Подмезанин 1 Зона 4
|
||||
172.16.54.49;Подмезанин 1 Зона 1
|
||||
172.16.54.50;Пандус Камера 3
|
||||
172.16.54.51;Антресоль 2 Фабрикон 1 new
|
||||
172.16.54.52;Антресоль 2 Фабрикон 2 new
|
||||
172.16.54.53;Антресоль 2 Фабрикон 3 new
|
||||
172.16.54.54;Антресоль 2 Фабрикон 4 new
|
||||
@@ -7,7 +7,7 @@
|
||||
<a class="nav-link active" aria-current="page" href="database">Сводные данные</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="database/addtype">Типы устройств</a>
|
||||
<a class="nav-link" href="database/type">Типы устройств</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
@page "/database/addtype"
|
||||
@using Ministreliy.Models
|
||||
|
||||
<PageTitle>База данных</PageTitle>
|
||||
|
||||
@if (listDT == null)
|
||||
{
|
||||
<p><em>Получаю данные...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" aria-current="page" href="database">Active</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="database/addtype">Добавить Тип</a>
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
}
|
||||
|
||||
@code {
|
||||
private DeviceType dt;
|
||||
private List<DeviceType> listDT;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
HttpClient http = new();
|
||||
http.BaseAddress = new Uri("http://localhost:5262/api/");
|
||||
var t = await http.GetAsync("Device/GetTypes");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
@page "/database/type"
|
||||
@using Ministreliy.Models
|
||||
@using System.Text.Json
|
||||
@using Newtonsoft.Json
|
||||
@using System.Text
|
||||
@inject IJSRuntime JS
|
||||
@inject NavigationManager NavManager
|
||||
|
||||
<PageTitle>База данных</PageTitle>
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" aria-current="page" href="database">Сводные данные</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="database/type">Типы устройств</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="modal fade modal1" id="addtype" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="addtypeLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="addtypeLabel">Заголовок</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label for="typeID" class="form-label">id типа</label>
|
||||
<input type="number" class="form-control" id="typeID" @bind="id_type" />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="typeName" class="form-label">Имя типа</label>
|
||||
<textarea class="form-control" id="typeName" rows="3" @bind="name_type"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" @onclick="SaveType">Сохранить</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@if (listDT.Count == 0 || listDT == null)
|
||||
{
|
||||
<p>@msg</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
@* <ul class="nav nav-tabs">
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link" aria-current="page" href="database">Сводные данные</a>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link active"
|
||||
id="addtype-tab"
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target="#addtype"
|
||||
role="tab"
|
||||
aria-controls="addtype"
|
||||
aria-selected="true"
|
||||
href="database/addtype">Добавить Тип</a>
|
||||
</li>
|
||||
|
||||
</ul> *@
|
||||
<br>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addtype">
|
||||
Добавить тип
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#deltype">
|
||||
Удалить тип
|
||||
</button>
|
||||
|
||||
<div class="card-body p-0">
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<!-- Панель 1: Главная -->
|
||||
<div class="tab-pane fade show active" id="addtype" role="tabpanel" aria-labelledby="addtype-tab">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Название</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in listDT)
|
||||
{
|
||||
<tr>
|
||||
<th scope="row">@item.Id</th>
|
||||
<td>@item.Name</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="modal fade modal2" id="deltype" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="deltypeLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="deltypeLabel">Заголовок</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<select class="form-select" @bind="selected_type" aria-label="Вибрать тип">
|
||||
@foreach (var item in listDT)
|
||||
{
|
||||
<option value="@item.Id">@item.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" @onclick="DelType">Удалить</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
//HttpClient http = new();
|
||||
|
||||
private DeviceType dt;
|
||||
private List<DeviceType> listDT = new();
|
||||
|
||||
private string msg = "-= ПОЛУЧАЮ ДАННЫЕ =-", name_type = "";
|
||||
private int id_type = 1, selected_type = 0;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
HttpClient http = new();
|
||||
await Task.Delay(1000);
|
||||
http.BaseAddress = new Uri("http://localhost:5262/api/");
|
||||
var t = await http.GetAsync("Device/GetTypes");
|
||||
if (t.StatusCode == System.Net.HttpStatusCode.NoContent)
|
||||
{
|
||||
msg = "-= ДАННЫХ НЕТ =-";
|
||||
}
|
||||
else
|
||||
{
|
||||
listDT = JsonConvert.DeserializeObject<List<DeviceType>>(await t.Content.ReadAsStringAsync());
|
||||
//id_type = listDT.Count + 1;
|
||||
var a = listDT.Select(listDT => listDT.Id).ToList();
|
||||
id_type = Enumerable.Range(1, int.MaxValue).FirstOrDefault(i => !a.Contains(i));
|
||||
|
||||
}
|
||||
}
|
||||
private async Task SaveType()
|
||||
{
|
||||
HttpClient http = new();
|
||||
dt = new();
|
||||
dt.Id = id_type;
|
||||
dt.Name = name_type;
|
||||
http.BaseAddress = new Uri("http://localhost:5262/api/");
|
||||
using StringContent content = new StringContent(
|
||||
JsonConvert.SerializeObject(dt),
|
||||
Encoding.UTF8,
|
||||
"application/json"
|
||||
);
|
||||
var r = await http.PostAsync("Device/AddType", content);
|
||||
if (r.IsSuccessStatusCode)
|
||||
{
|
||||
await JS.InvokeVoidAsync("eval", $"var myModal = bootstrap.Modal.getInstance(document.querySelector('.modal1')); myModal.hide();");
|
||||
await Task.Delay(150);
|
||||
id_type = listDT.Count+1;
|
||||
NavManager.NavigateTo(NavManager.Uri, forceLoad: true);
|
||||
}
|
||||
}
|
||||
private async Task DelType()
|
||||
{
|
||||
HttpClient http = new();
|
||||
http.BaseAddress = new Uri("http://localhost:5262/api/");
|
||||
var r = await http.DeleteAsync($"Device/DelType?id={selected_type}");
|
||||
if (r.IsSuccessStatusCode)
|
||||
{
|
||||
await JS.InvokeVoidAsync("eval", $"var myModal = bootstrap.Modal.getInstance(document.querySelector('.modal2')); myModal.hide();");
|
||||
await Task.Delay(250);
|
||||
id_type = listDT.Count + 1;
|
||||
NavManager.NavigateTo(NavManager.Uri, forceLoad: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
@page "/weather"
|
||||
|
||||
<PageTitle>Weather</PageTitle>
|
||||
|
||||
<h1>Weather</h1>
|
||||
|
||||
<p>This component demonstrates showing data.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Temp. (C)</th>
|
||||
<th>Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
private WeatherForecast[]? forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Simulate asynchronous loading to demonstrate a loading indicator
|
||||
await Task.Delay(500);
|
||||
|
||||
var startDate = DateOnly.FromDateTime(DateTime.Now);
|
||||
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
|
||||
forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = startDate.AddDays(index),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
Summary = summaries[Random.Shared.Next(summaries.Length)]
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
private class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
public int TemperatureC { get; set; }
|
||||
public string? Summary { get; set; }
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,8 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+4085
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,601 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.3.8 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2025 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
:root,
|
||||
[data-bs-theme=light] {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
line-height: inherit;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
[type=search]::-webkit-search-cancel-button {
|
||||
cursor: pointer;
|
||||
filter: grayscale(1);
|
||||
}
|
||||
|
||||
/* rtl:raw:
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
*/
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,598 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.3.8 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2025 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
:root,
|
||||
[data-bs-theme=light] {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-black: #000;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-primary-text-emphasis: #052c65;
|
||||
--bs-secondary-text-emphasis: #2b2f32;
|
||||
--bs-success-text-emphasis: #0a3622;
|
||||
--bs-info-text-emphasis: #055160;
|
||||
--bs-warning-text-emphasis: #664d03;
|
||||
--bs-danger-text-emphasis: #58151c;
|
||||
--bs-light-text-emphasis: #495057;
|
||||
--bs-dark-text-emphasis: #495057;
|
||||
--bs-primary-bg-subtle: #cfe2ff;
|
||||
--bs-secondary-bg-subtle: #e2e3e5;
|
||||
--bs-success-bg-subtle: #d1e7dd;
|
||||
--bs-info-bg-subtle: #cff4fc;
|
||||
--bs-warning-bg-subtle: #fff3cd;
|
||||
--bs-danger-bg-subtle: #f8d7da;
|
||||
--bs-light-bg-subtle: #fcfcfd;
|
||||
--bs-dark-bg-subtle: #ced4da;
|
||||
--bs-primary-border-subtle: #9ec5fe;
|
||||
--bs-secondary-border-subtle: #c4c8cb;
|
||||
--bs-success-border-subtle: #a3cfbb;
|
||||
--bs-info-border-subtle: #9eeaf9;
|
||||
--bs-warning-border-subtle: #ffe69c;
|
||||
--bs-danger-border-subtle: #f1aeb5;
|
||||
--bs-light-border-subtle: #e9ecef;
|
||||
--bs-dark-border-subtle: #adb5bd;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg: #fff;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-emphasis-color: #000;
|
||||
--bs-emphasis-color-rgb: 0, 0, 0;
|
||||
--bs-secondary-color: rgba(33, 37, 41, 0.75);
|
||||
--bs-secondary-color-rgb: 33, 37, 41;
|
||||
--bs-secondary-bg: #e9ecef;
|
||||
--bs-secondary-bg-rgb: 233, 236, 239;
|
||||
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
|
||||
--bs-tertiary-color-rgb: 33, 37, 41;
|
||||
--bs-tertiary-bg: #f8f9fa;
|
||||
--bs-tertiary-bg-rgb: 248, 249, 250;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #0d6efd;
|
||||
--bs-link-color-rgb: 13, 110, 253;
|
||||
--bs-link-decoration: underline;
|
||||
--bs-link-hover-color: #0a58ca;
|
||||
--bs-link-hover-color-rgb: 10, 88, 202;
|
||||
--bs-code-color: #d63384;
|
||||
--bs-highlight-color: #212529;
|
||||
--bs-highlight-bg: #fff3cd;
|
||||
--bs-border-width: 1px;
|
||||
--bs-border-style: solid;
|
||||
--bs-border-color: #dee2e6;
|
||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
||||
--bs-border-radius: 0.375rem;
|
||||
--bs-border-radius-sm: 0.25rem;
|
||||
--bs-border-radius-lg: 0.5rem;
|
||||
--bs-border-radius-xl: 1rem;
|
||||
--bs-border-radius-xxl: 2rem;
|
||||
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
|
||||
--bs-border-radius-pill: 50rem;
|
||||
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
|
||||
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--bs-focus-ring-width: 0.25rem;
|
||||
--bs-focus-ring-opacity: 0.25;
|
||||
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
|
||||
--bs-form-valid-color: #198754;
|
||||
--bs-form-valid-border-color: #198754;
|
||||
--bs-form-invalid-color: #dc3545;
|
||||
--bs-form-invalid-border-color: #dc3545;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] {
|
||||
color-scheme: dark;
|
||||
--bs-body-color: #dee2e6;
|
||||
--bs-body-color-rgb: 222, 226, 230;
|
||||
--bs-body-bg: #212529;
|
||||
--bs-body-bg-rgb: 33, 37, 41;
|
||||
--bs-emphasis-color: #fff;
|
||||
--bs-emphasis-color-rgb: 255, 255, 255;
|
||||
--bs-secondary-color: rgba(222, 226, 230, 0.75);
|
||||
--bs-secondary-color-rgb: 222, 226, 230;
|
||||
--bs-secondary-bg: #343a40;
|
||||
--bs-secondary-bg-rgb: 52, 58, 64;
|
||||
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
|
||||
--bs-tertiary-color-rgb: 222, 226, 230;
|
||||
--bs-tertiary-bg: #2b3035;
|
||||
--bs-tertiary-bg-rgb: 43, 48, 53;
|
||||
--bs-primary-text-emphasis: #6ea8fe;
|
||||
--bs-secondary-text-emphasis: #a7acb1;
|
||||
--bs-success-text-emphasis: #75b798;
|
||||
--bs-info-text-emphasis: #6edff6;
|
||||
--bs-warning-text-emphasis: #ffda6a;
|
||||
--bs-danger-text-emphasis: #ea868f;
|
||||
--bs-light-text-emphasis: #f8f9fa;
|
||||
--bs-dark-text-emphasis: #dee2e6;
|
||||
--bs-primary-bg-subtle: #031633;
|
||||
--bs-secondary-bg-subtle: #161719;
|
||||
--bs-success-bg-subtle: #051b11;
|
||||
--bs-info-bg-subtle: #032830;
|
||||
--bs-warning-bg-subtle: #332701;
|
||||
--bs-danger-bg-subtle: #2c0b0e;
|
||||
--bs-light-bg-subtle: #343a40;
|
||||
--bs-dark-bg-subtle: #1a1d20;
|
||||
--bs-primary-border-subtle: #084298;
|
||||
--bs-secondary-border-subtle: #41464b;
|
||||
--bs-success-border-subtle: #0f5132;
|
||||
--bs-info-border-subtle: #087990;
|
||||
--bs-warning-border-subtle: #997404;
|
||||
--bs-danger-border-subtle: #842029;
|
||||
--bs-light-border-subtle: #495057;
|
||||
--bs-dark-border-subtle: #343a40;
|
||||
--bs-heading-color: inherit;
|
||||
--bs-link-color: #6ea8fe;
|
||||
--bs-link-hover-color: #8bb9fe;
|
||||
--bs-link-color-rgb: 110, 168, 254;
|
||||
--bs-link-hover-color-rgb: 139, 185, 254;
|
||||
--bs-code-color: #e685b5;
|
||||
--bs-highlight-color: #dee2e6;
|
||||
--bs-highlight-bg: #664d03;
|
||||
--bs-border-color: #495057;
|
||||
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
|
||||
--bs-form-valid-color: #75b798;
|
||||
--bs-form-valid-border-color: #75b798;
|
||||
--bs-form-invalid-color: #ea868f;
|
||||
--bs-form-invalid-border-color: #ea868f;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
border: 0;
|
||||
border-top: var(--bs-border-width) solid;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: var(--bs-heading-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.1875em;
|
||||
color: var(--bs-highlight-color);
|
||||
background-color: var(--bs-highlight-bg);
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-code-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.1875rem 0.375rem;
|
||||
font-size: 0.875em;
|
||||
color: var(--bs-body-bg);
|
||||
background-color: var(--bs-body-color);
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: var(--bs-secondary-color);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
line-height: inherit;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
[type=search]::-webkit-search-cancel-button {
|
||||
cursor: pointer;
|
||||
filter: grayscale(1);
|
||||
}
|
||||
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+12048
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+12021
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6312
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4447
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4494
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -15,6 +15,7 @@ public class DeviceController : ControllerBase
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
//=========================== GET =================================//
|
||||
[HttpGet("GetTypes")]
|
||||
[ProducesResponseType<List<DeviceType>>(StatusCodes.Status200OK)]
|
||||
@@ -66,4 +67,17 @@ public class DeviceController : ControllerBase
|
||||
return Created();
|
||||
}
|
||||
}
|
||||
|
||||
//========================= DELETE ====================================//
|
||||
[HttpDelete("DelType")]
|
||||
public IActionResult DelType(int id)
|
||||
{
|
||||
using (var db = new SQLiteService())
|
||||
{
|
||||
var deldev = db.DeviceTypes.Where(u => u.Id == id).FirstOrDefault();
|
||||
db.DeviceTypes.Remove(deldev);
|
||||
db.SaveChanges();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
public int ConnectedToSwitchId { get; set; }
|
||||
public int ConnectedToPortOnSwitch { get; set; }
|
||||
|
||||
//public DeviceItem(int type, string ip, string mac, string location)
|
||||
//{
|
||||
public DeviceItem(string ip, string mac, string location)
|
||||
{
|
||||
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
//Unknown = 0,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+72
-3
@@ -75,7 +75,76 @@ Dictionary<string, string> listSw = new Dictionary<string, string>
|
||||
};
|
||||
List<string> listMac = new List<string>()
|
||||
{
|
||||
"b13b"
|
||||
"8bcb",
|
||||
"8c96",
|
||||
"8d44",
|
||||
"8be8",
|
||||
"fe71",
|
||||
"fb45",
|
||||
"fe54",
|
||||
"9e11",
|
||||
"fec8",
|
||||
"fe8e",
|
||||
"fa23",
|
||||
"8c79",
|
||||
"fb0b",
|
||||
"836d",
|
||||
"8316",
|
||||
"8c3f",
|
||||
"45e3",
|
||||
"fd32",
|
||||
"47ed",
|
||||
"8b3a",
|
||||
"4535",
|
||||
"822e",
|
||||
"8c22",
|
||||
"fb9c",
|
||||
"faee",
|
||||
"fda6",
|
||||
"fe37",
|
||||
"f9cc",
|
||||
"4861",
|
||||
"fd6c",
|
||||
"fde0",
|
||||
"f975",
|
||||
"fcf8",
|
||||
"fdfd",
|
||||
"4dee",
|
||||
"841b",
|
||||
"8d61",
|
||||
"8d27",
|
||||
"fc2d",
|
||||
"f9af",
|
||||
"8d0a",
|
||||
"8ced",
|
||||
"fd89",
|
||||
"4bc7",
|
||||
"fee5",
|
||||
"ff02",
|
||||
"4a6b",
|
||||
"9728",
|
||||
"9ea2",
|
||||
"8c05",
|
||||
"46e8",
|
||||
"8bae",
|
||||
"8cb3",
|
||||
"156d",
|
||||
"d887",
|
||||
"9e85",
|
||||
"d1f7",
|
||||
"96d1",
|
||||
"97b9",
|
||||
"9762",
|
||||
"9745",
|
||||
"886b",
|
||||
"86f2",
|
||||
"8155",
|
||||
"74d2",
|
||||
"7529",
|
||||
"7cdd",
|
||||
"9e4b",
|
||||
"155d",
|
||||
"93df"
|
||||
};
|
||||
|
||||
string host = "172.16.48.4";
|
||||
@@ -95,9 +164,8 @@ using (var client = new SshClient(host, port, username, password))
|
||||
{
|
||||
var command = client.RunCommand($"show mac-address | include {mac}");
|
||||
var otvet = command.Result.Split("\r\n")[1].Substring(45, 8);
|
||||
Console.WriteLine(listSw[otvet]);
|
||||
Console.WriteLine(otvet);// listSw[otvet]);
|
||||
}
|
||||
Console.ReadKey();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -111,4 +179,5 @@ using (var client = new SshClient(host, port, username, password))
|
||||
Console.WriteLine("Отключено.");
|
||||
}
|
||||
}
|
||||
Console.ReadKey();
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
<Solution>
|
||||
<Folder Name="/Faces/">
|
||||
<Project Path="FaceRecognitionApp/FaceRecognitionApp.csproj" Id="401c1b89-2e49-4ad0-8e88-0aff3edb4c6c" />
|
||||
</Folder>
|
||||
<Folder Name="/LC/">
|
||||
<Project Path="Ministreliy/Ministreliy.csproj" Id="ffd1e86c-d678-413c-a0fd-dd75b4ec1b2e" />
|
||||
<Project Path="Strela/Strela.csproj" />
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
})
|
||||
using (var httpClient = new HttpClient(handler))
|
||||
{
|
||||
string requestUrl = $"{baseUrlS}/cgi-bin/configManager.cgi?action=setConfig&SNMP.Enable=false";
|
||||
string requestUrl = $"{baseUrlS}/cgi-bin/configManager.cgi?action=setConfig&SNMP.Enable=false&SNMP.ReadCommon=public&SNMP.WriteCommon=private&SNMP.V2Enable=false";
|
||||
var response = await httpClient.GetAsync(requestUrl);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var r = response.ReasonPhrase;// .Content.ReadAsStringAsync();
|
||||
if (r.StartsWith("OK"))
|
||||
{
|
||||
string requestUrl2 = $"{baseUrlS}/cgi-bin/configManager.cgi?action=setConfig&SNMP.Enable=true";
|
||||
string requestUrl2 = $"{baseUrlS}/cgi-bin/configManager.cgi?action=setConfig&SNMP.Enable=true&SNMP.ReadCommon=public&SNMP.WriteCommon=private&SNMP.V2Enable=true";
|
||||
var response2 = await httpClient.GetAsync(requestUrl2);
|
||||
var r2 = response2.ReasonPhrase;//.Content.ReadAsStringAsync();
|
||||
if (r2.StartsWith("OK")) Console.WriteLine("0");
|
||||
|
||||
Reference in New Issue
Block a user