Добавил механизм удаления заготовок (ст.250 мониторинг)

This commit is contained in:
2025-05-26 23:26:41 +04:00
parent 83f1edcd9c
commit e8e9cdca3c
4 changed files with 276 additions and 22 deletions

4
Log.cs
View File

@@ -2,7 +2,10 @@
{ {
internal class Log internal class Log
{ {
private static object obj = new object();
public static void Logger(string str) public static void Logger(string str)
{
lock (obj)
{ {
string outdir = Environment.CurrentDirectory + @"\logs\"; string outdir = Environment.CurrentDirectory + @"\logs\";
if (!Directory.Exists(outdir)) Directory.CreateDirectory(outdir); if (!Directory.Exists(outdir)) Directory.CreateDirectory(outdir);
@@ -21,4 +24,5 @@
} }
} }
} }
}
} }

View File

@@ -1,6 +1,7 @@
using Microsoft.Data.SqlClient; using Microsoft.Data.SqlClient;
using Oracle.ManagedDataAccess.Client; using Oracle.ManagedDataAccess.Client;
using SendNotify; using SendNotify;
using System;
using System.Net; using System.Net;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Text; using System.Text;
@@ -8,18 +9,26 @@ using System.Text;
internal class Program internal class Program
{ {
private static DateTime lastDate = DateTime.MinValue; private static DateTime lastDate = DateTime.MinValue;
private static DateTime startProgramDT = DateTime.MinValue;
public static bool statusRemovingBillets = false;
private static CancellationTokenSource? removalCts;
private static object removalLock = new object();
private static void Main(string[] args) private static void Main(string[] args)
{ {
startProgramDT = DateTime.Now;
var RemovingBillets = new RemovingBillets();
while (true) while (true)
{ {
string? gotifyUrl = null; string? gotifyUrl = null;
string? appToken_izhstal = null; string? appToken_izhstal = null;
string? clientToken_izhstal = null;
string? proxyUrl = null; string? proxyUrl = null;
string? proxyUsername = null; string? proxyUsername = null;
string? proxyPassword = null; string? proxyPassword = null;
string? checkNow = null; string? checkNow = null;
int targetPriority = -1;
var config = File.ReadAllLines("config.txt"); var config = File.ReadAllLines("config.txt");
@@ -37,23 +46,52 @@ internal class Program
proxyPassword = line.Substring("proxy_password=".Length); proxyPassword = line.Substring("proxy_password=".Length);
else if (line.StartsWith("check_now=")) else if (line.StartsWith("check_now="))
checkNow = line.Substring("check_now=".Length); checkNow = line.Substring("check_now=".Length);
else if (line.StartsWith("client_token_izhstal="))
clientToken_izhstal = line.Substring("client_token_izhstal=".Length);
else if (line.StartsWith("target_priority="))
int.TryParse(line.Substring("target_priority=".Length), out targetPriority);
} }
if (gotifyUrl == null || appToken_izhstal == null || proxyUrl == null || proxyUsername == null || proxyPassword == null || checkNow == null) if (gotifyUrl == null || appToken_izhstal == null || proxyUrl == null || proxyUsername == null ||
proxyPassword == null || checkNow == null || clientToken_izhstal == null || targetPriority == -1)
{ {
Console.WriteLine("Ошибка: не все параметры указаны в config.txt"); Console.WriteLine("Ошибка: не все параметры указаны в config.txt");
Log.Logger("Ошибка: не все параметры указаны в config.txt"); Log.Logger("Ошибка: не все параметры указаны в config.txt");
} }
else else
{ {
NotifyPollingAsync(gotifyUrl, appToken_izhstal, proxyUrl, proxyUsername, proxyPassword, checkNow); NotifyPollingAsync(gotifyUrl, appToken_izhstal, proxyUrl, proxyUsername, proxyPassword, checkNow);
} var result = ReceiveMessagesAsync(gotifyUrl, clientToken_izhstal, proxyUrl, proxyUsername, proxyPassword, targetPriority).Result;
if (result.status && result.msg.Date > startProgramDT)
{
if (result.msg.Title == "L2_REM")
{
lock (removalLock)
{
if (result.msg.Message == "ON" && !statusRemovingBillets)
{
removalCts = new CancellationTokenSource();
Task.Run(() => RemovingBillets.StartRemovalProcess(removalCts.Token));
statusRemovingBillets = true;
Log.Logger("Удаление заготовок: ЗАПУЩЕНО");
}
else if (result.msg.Message == "OFF" && statusRemovingBillets)
{
removalCts?.Cancel();
statusRemovingBillets = false;
Log.Logger("Удаление заготовок: ОСТАНОВЛЕНО");
}
}
}
}
}
Thread.Sleep(60000); Thread.Sleep(60000);
} }
} }
private static async void NotifyPollingAsync(string url, string token, string proxyUrl, string proxyUsername, string proxyPassword, string checkNow) private static async void NotifyPollingAsync(string url, string token, string proxyUrl, string proxyUsername, string proxyPassword, string checkNow)
{ {
#region test msg to check #region test msg to check
@@ -213,7 +251,8 @@ internal class Program
try try
{ {
HttpResponseMessage response = await client.PostAsync(url, content); var requestUrl = $"{url}/message";
HttpResponseMessage response = await client.PostAsync(requestUrl, content);
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@@ -238,5 +277,74 @@ internal class Program
} }
} }
} }
} private static async Task<(bool status, GotifyMessage msg)> ReceiveMessagesAsync(
string url,
string token,
string proxyUrl,
string proxyUsername,
string proxyPassword,
int targetPriority)
{
var proxy = new WebProxy(new Uri(proxyUrl))
{
Credentials = new NetworkCredential(proxyUsername, proxyPassword, "MECHEL")
};
var handler = new HttpClientHandler()
{
Proxy = proxy,
UseProxy = true,
PreAuthenticate = true,
UseDefaultCredentials = false
};
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Add("X-Gotify-Key", token);
var requestUrl = $"{url}/message?limit=100";
try
{
var response = await client.GetAsync(requestUrl);
if (response.IsSuccessStatusCode)
{
var messages = await response.Content.ReadFromJsonAsync<GotifyMessagesResponse>();
var filtered = messages.Messages?
.Where(m => m.Priority == targetPriority)
.OrderByDescending(m => m.Date)
.ToList();
if (filtered?.Count > 0)
{
var lastMsg = filtered.First();
return (true, lastMsg);
}
return (false, null);
}
Console.WriteLine($"Ошибка HTTP: {response.StatusCode}");
return (false, null);
}
catch (Exception ex)
{
Console.WriteLine($"Ошибка: {ex.Message}");
Log.Logger($"Ошибка получения сообщений: {ex.Message}");
return (false, null);
}
}
}
public class GotifyMessagesResponse
{
public required List<GotifyMessage> Messages { get; set; }
}
public class GotifyMessage
{
public string? Title { get; set; }
public string? Message { get; set; }
public int Priority { get; set; }
public DateTime Date { get; set; }
}
}

140
RemovingBillets.cs Normal file
View File

@@ -0,0 +1,140 @@
using Oracle.ManagedDataAccess.Client;
using SendNotify;
using System.Data;
public class RemovingBillets
{
private static readonly object _syncRoot = new object();
private static bool _isProcessActive = false;
private static DateTime _lastCheckTime = DateTime.MinValue;
public static async Task StartRemovalProcess(CancellationToken ct)
{
lock (_syncRoot)
{
if (_isProcessActive)
{
Log.Logger("Процесс удаления уже запущен");
return;
}
_isProcessActive = true;
}
Log.Logger("Процесс удаления: СТАРТ");
try
{
using (var periodicTimer = new PeriodicTimer(TimeSpan.FromSeconds(5)))
{
while (await periodicTimer.WaitForNextTickAsync(ct))
{
if (ct.IsCancellationRequested)
break;
try
{
var result = await CheckAndSendAlerts(ct);
if (!result)
{
Log.Logger("Нет заготовок для удаления - остановка");
break;
}
_lastCheckTime = DateTime.Now;
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
Log.Logger($"Ошибка в процессе удаления: {ex.Message}");
}
}
}
}
catch (OperationCanceledException)
{
Log.Logger("Процесс удаления: ОСТАНОВЛЕН ПО ТРЕБОВАНИЮ");
}
finally
{
lock (_syncRoot)
{
_isProcessActive = false;
}
Program.statusRemovingBillets = false;
Log.Logger("Процесс удаления: ФИНАЛИЗАЦИЯ");
}
}
private static async Task<bool> CheckAndSendAlerts(CancellationToken ct)
{
const string oracleConn = "User Id=main;Password=main;Data Source=10.14.18.50:1521/izl2;";
try
{
using var conn = new OracleConnection(oracleConn);
await conn.OpenAsync(ct);
var products = await GetTrackedProducts(conn, ct);
if (!products.Any()) return false;
foreach (var product in products)
{
ct.ThrowIfCancellationRequested();
await SendToRoll(product.ProductId, conn, ct);
Thread.Sleep(5000);
}
return true;
}
catch
{
throw;
}
}
private static async Task<List<ProductInfo>> GetTrackedProducts(OracleConnection conn, CancellationToken ct)
{
var result = new List<ProductInfo>();
using var cmd = conn.CreateCommand();
cmd.CommandText = @"
SELECT
product_id,
DISCHARGING_DATI
FROM V_TRACKING_MILL
WHERE DISCHARGING_DATI > :last_check";
cmd.Parameters.Add("last_check", OracleDbType.Date).Value = _lastCheckTime;
using var reader = await cmd.ExecuteReaderAsync(ct);
while (await reader.ReadAsync(ct))
{
result.Add(new ProductInfo
{
ProductId = reader.GetInt32(0),
CreatedDate = reader.GetDateTime(1)
});
}
return result;
}
private static async Task SendToRoll(int productId, OracleConnection conn, CancellationToken ct)
{
using var cmd = conn.CreateCommand();
cmd.CommandText = "dbms_alert.signal";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("name", "UI_ALERT_IZH"));
cmd.Parameters.Add(new OracleParameter("message", $"send_finish_mill {productId}"));
await cmd.ExecuteNonQueryAsync(ct);
Log.Logger($"Отправлен сигнал удаления для ID: {productId}");
}
}
public class ProductInfo
{
public int ProductId { get; set; }
public DateTime CreatedDate { get; set; }
}

View File

@@ -1,6 +1,8 @@
gotify_url=https://gtf.mysrvhateapple.duckdns.org/message gotify_url=https://gtf.mysrvhateapple.duckdns.org
app_token_izhstal=A6i4cMWOMSikvsR app_token_izhstal=A6i4cMWOMSikvsR
proxy_url=http://10.14.0.14:3128 proxy_url=http://10.14.0.14:3128
proxy_username=KhasanovAM proxy_username=KhasanovAM
proxy_password=Prokatka49! proxy_password=Prokatka49!
check_now=no check_now=no
client_token_izhstal=C3r-LxgBxnxyMH.
target_priority=7