agrobot_base/AgroBase/AgroBase/Models/Variaveis.cs

979 lines
36 KiB
C#

using AgroBase.Models.Modules;
using AgroBase.Services;
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using static AgroBase.Models.Enums;
using System.Drawing.Drawing2D;
using Microsoft.Win32;
using System.Reflection;
using CefSharp.WinForms;
using System.IO;
using System.Threading;
namespace AgroBase.Models
{
public class Variaveis
{
public static string CaminhoSistema { get; set; } = AppDomain.CurrentDomain.BaseDirectory;
public static string NomeAplicacao
{
get
{
Assembly assembly = Assembly.GetExecutingAssembly();
string name = assembly.GetName().Name;
return name.ToString();
}
}
public static string Versao
{
get
{
Assembly assembly = Assembly.GetExecutingAssembly();
Version version = assembly.GetName().Version;
return version.ToString();
}
}
public static string CaminhoLogsDispositivos { get; } = "Logs/";
public static string CaminhoOperacoes { get; } = "Operacoes/";
public static string CaminhoOperacoesSalvas { get; } = "OperacoesSalvas\\";
public static string CaminhoMapasConvertidos { get; } = "Mapas/";
public static string CaminhoParametros { get; } = "Parametros/";
public static string CaminhoModelos { get; } = "C:\\AgroBaseModels\\";
public static List<IDispositivosService> DispositivosConectados { get; set; } = new List<IDispositivosService>();
public static OperacaoModel OperacaoEmAndamento { get; set; } = new OperacaoModel(ModoOperacao.Manual);
public static MqttService MqttService { get; set; } = new MqttService("localhost", 1883);
public static LoRaService ConexaoLoRa = new LoRaService();
public static string FaixaIPwifi { get; set; } = "192.168.100";
public static string FaixaIPethernet { get; set; } = "192.168.105";
public static string IP_Host { get; set; } = FaixaIPwifi + ".105";
public static string NomeRedeWifiEquipamento { get; set; } = "Agrobot";
public static string SenhaRedeWifiEquipamento { get; set; } = "4321agro";
public static bool IsAgroMonitor
{
get
{
return CaminhoSistema.Contains("AgroMonitor");
}
}
}
public static class VariaveisPortas
{
public static int CameraSolo { get; } = 6522;
public static int CameraCaminho { get; } = 6544;
public static int Ethernet_AT { get; } = 8899;
public static int Ethernet_TCP { get; } = 8899;
}
public static class VariaveisEquipamento
{
public static double LarguraEsquerda { get; } = 40;
public static double LarguraDireita { get; } = 40;
public static double LarguraEquipamentoMm
{
get
{
return ((LarguraEsquerda + LarguraDireita + 20) * 10);
}
}
public static double PercentualTensaoBateriaMin { get; set; } = 25.0;
public static double PercentualReservatorioMin { get; set; } = 5.0;
public static double PercentualToleranciaPressaoLinha { get; set; } = 0.15;
public static double ReducaoDirecional { get; set; } = 20.0;
public static int RPM_Max_Roda
{
get
{
double RpmMax =
Variaveis.OperacaoEmAndamento.DispMvd != null ?
Variaveis.OperacaoEmAndamento.DispMvd.Dados.RPM_Max_MotorBLDC / RelacaoRPM :
100;
return (int)RpmMax;
}
}
public static double RelacaoRPM
{
get
{
double RelacaoRPM =
Variaveis.OperacaoEmAndamento.DispMvd != null ?
Variaveis.OperacaoEmAndamento.DispMvd.Dados.ReducaoMotorBLDC :
1;
return RelacaoRPM;
}
}
public static double DiametroRoda
{
get
{
double diametro =
Variaveis.OperacaoEmAndamento.DispMvd != null ?
Variaveis.OperacaoEmAndamento.DispMvd.Dados.DiametroRoda :
0.3556;
return diametro;
}
}
public static int TempoEntrePingsConexao { get; set; } = 10000;
public static Dictionary<AcaoFreio, int> AnguloFreio { get; } = new Dictionary<AcaoFreio, int>()
{
{ AcaoFreio.Ativar, 15 },
{ AcaoFreio.Desativar, 0 }
};
public static Dictionary<TipoMovimentoDirecional, int> AnguloMovimento { get; } = new Dictionary<TipoMovimentoDirecional, int>()
{
{ TipoMovimentoDirecional.RodasDianteiras, -1 },
{ TipoMovimentoDirecional.RodasTraseiras, -1 },
{ TipoMovimentoDirecional.MovimentoDiagonal, -1 },
{ TipoMovimentoDirecional.MovimentoArco, -1 },
{ TipoMovimentoDirecional.RotacionarNoEixo, 45 },
{ TipoMovimentoDirecional.MovimentoLateral, 90 },
{ TipoMovimentoDirecional.Diagnostico, 25 },
};
public static SensorSinaleiroComportamentoModel ComportamentoPorStatus(StatusOperacao? _status = null)
{
if (_status == null)
{
_status = Variaveis.OperacaoEmAndamento.StatusAtual;
}
SensorSinaleiroComportamentoModel comportamento = new SensorSinaleiroComportamentoModel()
{
statusLED = StatusLED.Apagado,
QtdPiscadas = 0,
TempoMs = 0,
PausaMs = 0,
};
switch (_status)
{
case StatusOperacao.Parametrizando:
{
comportamento = new SensorSinaleiroComportamentoModel()
{
statusLED = StatusLED.Piscando,
QtdPiscadas = 2,
TempoMs = 500,
PausaMs = 2000,
};
break;
}
case StatusOperacao.NaoIniciado:
case StatusOperacao.Concluido:
{
comportamento = new SensorSinaleiroComportamentoModel()
{
statusLED = StatusLED.Piscando,
QtdPiscadas = 1,
TempoMs = 1000,
PausaMs = 1000,
};
break;
}
case StatusOperacao.Aguardando:
{
comportamento = new SensorSinaleiroComportamentoModel()
{
statusLED = StatusLED.Piscando,
QtdPiscadas = 2,
TempoMs = 1000,
PausaMs = 2000,
};
break;
}
case StatusOperacao.Parado:
{
comportamento = new SensorSinaleiroComportamentoModel()
{
statusLED = StatusLED.Piscando,
QtdPiscadas = 4,
TempoMs = 200,
PausaMs = 1000,
};
break;
}
case StatusOperacao.EmAndamento:
{
comportamento = new SensorSinaleiroComportamentoModel()
{
statusLED = StatusLED.Piscando,
QtdPiscadas = 3,
TempoMs = 200,
PausaMs = 2000,
};
break;
}
}
return comportamento;
}
}
public static class VariaveisOperacao
{
public static double TempoManobra { get; set; } = 10;
public static double PercentualComErvas
{
get
{
if (!Variaveis.IsAgroMonitor && Variaveis.OperacaoEmAndamento.DispAtu != null)
{
return Variaveis.OperacaoEmAndamento.Sensoriamento.PercentualErvasTerreno / 100.0;
}
return 0.3;
}
}
public static double PercentualSemErvas
{
get
{
if (!Variaveis.IsAgroMonitor && Variaveis.OperacaoEmAndamento.DispAtu != null)
{
return (100.0 - Variaveis.OperacaoEmAndamento.Sensoriamento.PercentualErvasTerreno) / 100.0;
}
return 0.7;
}
}
public static GPSModel PosicaoBase { get; set; }
}
public static class FuncoesGlobais
{
public static void AddApplicationToStartup()
{
string appName = Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyTitleAttribute>()?.Title ?? "DefaultAppName";
string appPath = Application.ExecutablePath;
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
if (registryKey.GetValue(appName) == null)
{
registryKey.SetValue(appName, appPath);
}
}
public static string TimestampToDate(double timestamp, string Formatacao = "HH:mm:ss.fff")
{
// Converta o timestamp Unix para DateTime
// A época Unix começa em 1 de janeiro de 1970
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime date = epoch.AddSeconds(timestamp);
// Converter a data UTC para a data no fuso horário local do sistema
DateTime localDate = date.ToLocalTime();
// Formate a data para hh:mm:ss.fff (note a correção de MM para mm)
string formattedDate = localDate.ToString(Formatacao, System.Globalization.CultureInfo.InvariantCulture);
return formattedDate;
}
public static T FindControlRecursive<T>(Control parent, string controlName) where T : Control
{
foreach (Control child in parent.Controls)
{
if (child is T foundControl && child.Name == controlName)
{
return foundControl; // Retorna o controle se encontrado
}
else
{
T foundInChildren = FindControlRecursive<T>(child, controlName);
if (foundInChildren != null) return foundInChildren; // Retorna o controle se encontrado em controles filhos
}
}
return null; // Retorna null se o controle não for encontrado
}
public static void PreencheValorProgressBar(ProgressBar pgb, double Valor)
{
pgb.Value =
Valor >= pgb.Minimum && Valor <= pgb.Maximum ? pgb.Value = Convert.ToInt32(Valor) :
Valor < pgb.Minimum ? pgb.Value = pgb.Minimum :
Valor > pgb.Maximum ? pgb.Value = pgb.Maximum :
pgb.Minimum;
}
public static void PreencheValorTrackBar(TrackBar tkb, double Valor)
{
tkb.Value =
Valor >= tkb.Minimum && Valor <= tkb.Maximum ? tkb.Value = Convert.ToInt32(Valor) :
Valor < tkb.Minimum ? tkb.Value = tkb.Minimum :
Valor > tkb.Maximum ? tkb.Value = tkb.Maximum :
tkb.Minimum;
}
// Método para salvar o frame atual em JPEG
public static void SalvarFrameJPEG(Bitmap frame, string caminhoArquivo)
{
// Define as opções de codificação JPEG (qualidade de 90%)
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90L);
// Salva o bitmap em formato JPEG
ImageCodecInfo jpegCodec = GetEncoderInfo(ImageFormat.Jpeg);
frame.Save(caminhoArquivo, jpegCodec, encoderParams);
}
// Método auxiliar para obter informações do codec JPEG
private static ImageCodecInfo GetEncoderInfo(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
public static ImageCodecInfo GetEncoderInfo(string mimeType)
{
// Obtém todos os codecs de imagem disponíveis
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
// Procura pelo codec que corresponde ao mimeType fornecido
foreach (ImageCodecInfo codec in codecs)
{
if (codec.MimeType == mimeType)
{
return codec;
}
}
return null;
}
public static Image EspelharImagemHorizontalmente(Image img)
{
// Cria uma cópia da imagem do PictureBox
Bitmap originalImage = new Bitmap(img);
// Cria uma nova imagem para conter a imagem espelhada
Bitmap mirroredImage = new Bitmap(originalImage.Width, originalImage.Height);
// Cria uma matriz de transformação para espelhar horizontalmente
Matrix matrix = new Matrix();
matrix.Scale(-1, 1);
// Cria um objeto Graphics para desenhar a imagem espelhada
using (Graphics g = Graphics.FromImage(mirroredImage))
{
// Espelha a imagem original na nova imagem
g.Transform = matrix;
g.DrawImage(originalImage, new Rectangle(-originalImage.Width, 0, originalImage.Width, originalImage.Height));
}
return mirroredImage;
}
// Método para rotacionar a imagem
public static Image RotacionarImagem(Image img, double rotationAngle, bool redimensionarParaCaber = true)
{
// Calcula as novas dimensões do bitmap com base na rotação
double angleRad = rotationAngle / 180.0 * Math.PI;
double sin = Math.Abs(Math.Sin(angleRad));
double cos = Math.Abs(Math.Cos(angleRad));
int newWidth = (int)(img.Width * cos + img.Height * sin);
int newHeight = (int)(img.Width * sin + img.Height * cos);
Bitmap bmp;
if (redimensionarParaCaber)
{
// Cria um novo bitmap com as dimensões calculadas
bmp = new Bitmap(newWidth, newHeight);
}
else
{
// Cria um novo bitmap com as dimensões originais
bmp = new Bitmap(img.Width, img.Height);
}
using (Graphics gfx = Graphics.FromImage(bmp))
{
gfx.Clear(Color.Transparent); // Define a cor de fundo como transparente
if (redimensionarParaCaber)
{
gfx.TranslateTransform(newWidth / 2f, newHeight / 2f); // Move o ponto de rotação para o centro do novo bitmap
}
else
{
gfx.TranslateTransform(img.Width / 2f, img.Height / 2f); // Move o ponto de rotação para o centro do bitmap original
}
gfx.RotateTransform((float)rotationAngle); // Aplica a rotação
if (redimensionarParaCaber)
{
gfx.TranslateTransform(-img.Width / 2f, -img.Height / 2f); // Move a imagem de volta para o centro
}
else
{
gfx.TranslateTransform(-img.Width / 2f, -img.Height / 2f); // Move a imagem de volta para o centro
}
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfx.DrawImage(img, 0, 0, img.Width, img.Height); // Desenha a imagem original no bitmap
}
return bmp;
}
public static void DesenharInclinacao(Panel pnlBussola, PaintEventArgs e, float anguloInclinacao, float anguloSub)
{
if (!(anguloInclinacao >= 0 || anguloInclinacao <= 0))
{
anguloInclinacao = 0;
}
Graphics g = e.Graphics;
// Desenha o círculo da bússola
int diameter = Math.Min(pnlBussola.Width - 1, pnlBussola.Height - 1);
Point centro = new Point((pnlBussola.Width - 1) / 2, (pnlBussola.Height - 1) / 2);
//g.DrawEllipse(Pens.Black, centro.X - diameter / 2, centro.Y - diameter / 2, diameter, diameter);
// Escreve o ângulo no centro do círculo
string anguloTexto = $"{anguloInclinacao.ToString("0")}°";
Font fonteAngulo = new Font("Arial", 7); // Ajuste o tamanho da fonte conforme necessário
SizeF textSize = e.Graphics.MeasureString(anguloTexto, fonteAngulo);
// Calcula a posição para o texto ser centralizado no círculo
float textX = 0;
float textY = 0;
// Define a cor do texto
Brush textBrush = Brushes.Black;
// Desenha o texto no Graphics do painel
g.DrawString(anguloTexto, fonteAngulo, textBrush, textX, textY);
// A linha será desenhada do centro do círculo
PointF pontoCentral = new PointF(centro.X, centro.Y);
// O comprimento da linha será metade do diâmetro do círculo (raio)
float comprimentoLinha = diameter / 3;
// Ajustar o ângulo para que 0 graus esteja para cima e aumente no sentido horário
//float anguloRadianos = (anguloInclinacao - 90) * (float)(Math.PI / 180.0);
float anguloRadianos = (anguloInclinacao - anguloSub) * (float)(Math.PI / 180.0);
// Calcular o ponto final da linha baseado no ângulo de inclinação
PointF pontoFinal = new PointF(
pontoCentral.X + comprimentoLinha * (float)Math.Cos(anguloRadianos),
pontoCentral.Y + comprimentoLinha * (float)Math.Sin(anguloRadianos)
);
// Desenhar a linha de inclinação
g.DrawLine(Pens.Red, pontoCentral, pontoFinal);
// Opcional: Desenhar uma ponta de seta na linha para indicar direção
using (AdjustableArrowCap bigArrow = new AdjustableArrowCap(4, 4))
{
using (Pen pen = new Pen(Color.Red, 2))
{
pen.CustomEndCap = bigArrow;
g.DrawLine(pen, pontoCentral, pontoFinal);
}
}
}
public static string ConverterSegundosParaHHmmss(int totalSeconds)
{
TimeSpan timeSpan = TimeSpan.FromSeconds(totalSeconds);
return timeSpan.ToString(@"hh\:mm\:ss");
}
public static void DelaySincrono(int ms)
{
DateTime Agora = DateTime.Now;
while (Agora < DateTime.Now.AddMilliseconds(-ms)) { }
}
public static void DefinirEventosPicBtn(Control ctrl, string mensagemErro, Func<Task> func, bool hover = false)
{
ctrl.Cursor = Cursors.Hand;
// Adiciona eventos de hover (evita múltiplos registros)
if (hover)
{
ctrl.MouseEnter -= picBtn_MouseEnter;
ctrl.MouseLeave -= picBtn_MouseLeave;
ctrl.MouseEnter += picBtn_MouseEnter;
ctrl.MouseLeave += picBtn_MouseLeave;
}
// Remove eventos anteriores e adiciona o novo
ctrl.Click -= async (s, args) => await HandlePicBtnClick(ctrl, mensagemErro, func);
ctrl.Click += async (s, args) => await HandlePicBtnClick(ctrl, mensagemErro, func);
}
private static async Task HandlePicBtnClick(Control ctrl, string mensagemErro, Func<Task> func)
{
try
{
// Executa o efeito de piscada antes da ação
await PiscarBtn(ctrl, 2);
// Executa a ação associada ao botão
if (func != null)
{
await func();
}
}
catch (Exception ex)
{
// Exibe uma mensagem de erro genérica para qualquer exceção
MessageBox.Show($"{mensagemErro}\nDetalhes: {ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public static void picBtn_MouseEnter(object sender, EventArgs e)
{
TransicaoTamanho((Control)sender, true, 5).ConfigureAwait(false);
}
public static void picBtn_MouseLeave(object sender, EventArgs e)
{
TransicaoTamanho((Control)sender, false, 5).ConfigureAwait(false);
}
private static void AlteraTamanhoObjeto(Control ctrl, bool Cresce)
{
int acX = Convert.ToInt32(ctrl.Width * 0.06);
if (acX % 2 == 1) acX++;
int acY = Convert.ToInt32(ctrl.Height * 0.06);
if (acY % 2 == 1) acY++;
if (!Cresce)
{
acX *= -1;
acY *= -1;
}
ctrl.Size = new Size((int)(ctrl.Width + acX), (int)(ctrl.Height + acY));
ctrl.Location = new Point(ctrl.Location.X - (acX / 2), ctrl.Location.Y - (acY / 2));
}
private static async Task TransicaoTamanho(Control ctrl, bool Cresce, int delay)
{
int steps = 10; // Número de passos na transição
int acX = Convert.ToInt32(ctrl.Width * 0.06);
if (acX % 2 == 1) acX++;
int acY = Convert.ToInt32(ctrl.Height * 0.06);
if (acY % 2 == 1) acY++;
// Ajuste para garantir que stepX e stepY sejam pelo menos 2
int stepX = Math.Max(acX / steps, 2);
int stepY = Math.Max(acY / steps, 2);
if (!Cresce)
{
stepX = -stepX;
stepY = -stepY;
}
for (int i = 0; i < steps; i++)
{
ctrl.Invoke((MethodInvoker)(() =>
{
ctrl.Size = new Size(ctrl.Width + stepX, ctrl.Height + stepY);
ctrl.Location = new Point(ctrl.Location.X - (stepX / 2), ctrl.Location.Y - (stepY / 2));
}));
await Task.Delay(delay);
}
}
private static async Task PiscarBtn(Control ctrl, int vezes)
{
for (int i = 0; i < vezes; i++)
{
await TransicaoTamanho(ctrl, true, 1);
await Task.Delay(3);
await TransicaoTamanho(ctrl, false, 1);
await Task.Delay(3);
}
}
public static Bitmap GetPanelImage(Panel panel)
{
// Cria um bitmap do tamanho do panel
Bitmap bitmap = new Bitmap(panel.Width, panel.Height);
// Desenha o conteúdo do panel no bitmap
panel.DrawToBitmap(bitmap, new Rectangle(0, 0, panel.Width, panel.Height));
// Retorna o bitmap
return bitmap;
}
public static async Task<Bitmap> GetBrowserImage(ChromiumWebBrowser browser)
{
if (browser != null)
{
var screenshot = await browser.CaptureScreenshotAsync();
using (var stream = new MemoryStream(screenshot))
{
var bitmap = new Bitmap(stream);
return bitmap;
}
}
return null;
}
public static void SalvarImagemComprimida(Bitmap frame, string Caminho, long qualidade)
{
// Se o frame for nulo, cria um novo bitmap representando uma tela preta
if (frame == null)
{
frame = new Bitmap(1, 1);
using (Graphics g = Graphics.FromImage(frame))
{
g.Clear(Color.Black);
}
}
// Obtém o codec para JPEG
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
// Configura os parâmetros de compressão
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualidade);
using (Graphics g = Graphics.FromImage(frame))
{
g.DrawString(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss"), new Font("Arial", 10), Brushes.Transparent, new PointF(10, 10));
}
// Salva a imagem com a qualidade ajustada
frame.Save(Caminho, jpegCodec, encoderParams);
}
public static void SalvarImagemComprimida(Bitmap frame, string Caminho, long qualidade, int larguraDestino, int alturaDestino)
{
// Se o frame for nulo, cria um novo bitmap representando uma tela preta
if (frame == null)
{
larguraDestino = 1;
alturaDestino = 1;
frame = new Bitmap(larguraDestino, alturaDestino);
using (Graphics g = Graphics.FromImage(frame))
{
g.Clear(Color.Black);
}
}
Color corBorda = Color.FromArgb(14, 14, 14);
// Remover bordas pretas
Bitmap frameSemBordas = RemoverBordasPretas(frame, corBorda);
// Criar o novo bitmap redimensionado para o tamanho de destino
Bitmap bitmapRedimensionado = new Bitmap(larguraDestino, alturaDestino);
// Redimensionar a imagem original para ocupar toda a área de 512x512
using (Graphics g = Graphics.FromImage(bitmapRedimensionado))
{
// Configurações de alta qualidade para minimizar a perda de qualidade durante o redimensionamento
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
// Preencher o bitmap de destino (512x512) com a imagem redimensionada
g.DrawImage(frameSemBordas, 0, 0, larguraDestino, alturaDestino);
// Adiciona a data e hora na imagem (opcional)
g.DrawString(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss"), new Font("Arial", 10), Brushes.Transparent, new PointF(10, 10));
}
// Obtém o codec para JPEG
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
// Configura os parâmetros de compressão
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualidade);
// Salva a imagem redimensionada com a qualidade ajustada
bitmapRedimensionado.Save(Caminho, jpegCodec, encoderParams);
// Libera os recursos usados pelo bitmap redimensionado
bitmapRedimensionado.Dispose();
}
private static Bitmap RemoverBordasPretas(Bitmap _imagem, Color corBorda)
{
Bitmap imagem = (Bitmap)_imagem.Clone();
int xMin = imagem.Width, xMax = 0, yMin = imagem.Height, yMax = 0;
// Iterar sobre todos os pixels para encontrar os limites da imagem sem bordas com a cor especificada
for (int y = 0; y < imagem.Height; y++)
{
for (int x = 0; x < imagem.Width; x++)
{
Color pixel = imagem.GetPixel(x, y);
// Verificar se o pixel não corresponde à cor da borda
if (pixel.R != corBorda.R || pixel.G != corBorda.G || pixel.B != corBorda.B)
{
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
}
}
// Se a imagem for completamente da cor da borda, retornar um bitmap vazio
if (xMax == 0 && yMax == 0)
{
return new Bitmap(1, 1); // Imagem completamente da cor da borda
}
// Cortar a imagem para remover as bordas
int novaLargura = xMax - xMin + 1;
int novaAltura = yMax - yMin + 1;
Bitmap imagemSemBordas = new Bitmap(novaLargura, novaAltura);
using (Graphics g = Graphics.FromImage(imagemSemBordas))
{
g.DrawImage(imagem, new Rectangle(0, 0, novaLargura, novaAltura), new Rectangle(xMin, yMin, novaLargura, novaAltura), GraphicsUnit.Pixel);
}
return imagemSemBordas;
}
public static async Task ExecutarMetodoComVerificacaoCrossThreadAsync(Control controle, Func<Task> acao)
{
if (controle.InvokeRequired)
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
controle.BeginInvoke(new Action(async () =>
{
try
{
await acao();
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}));
await tcs.Task;
}
else
{
await acao();
}
}
public static T ExecutarMetodoComVerificacaoCrossThread<T>(Control controle, Func<T> acao)
{
if (controle == null)
throw new ArgumentNullException(nameof(controle));
try
{
if (controle.InvokeRequired)
{
return (T)controle.Invoke(new Func<T>(() => acao()));
}
else
{
return acao();
}
}
catch (Exception ex)
{
// Log ou tratamento da exceção
Console.WriteLine($"Erro em ExecutarMetodoComVerificacaoCrossThread: {ex.Message}");
throw; // Relançar a exceção para quem chamou lidar com ela, se necessário
}
}
public static string MontarStringPerformance(float? gpuLoad, float? cpuLoad, float? ramUsage, float? cpuTemp, float? gpuTemp)
{
return $"GPU: {gpuLoad?.ToString("0.0") ?? "N/A"}% " +
$"CPU: {cpuLoad?.ToString("0.0") ?? "N/A"}% " +
$"RAM: {ramUsage?.ToString("0.0") ?? "N/A"}% " +
$"Temp CPU: {cpuTemp?.ToString("0.0") ?? "N/A"}°C " +
$"Temp GPU: {gpuTemp?.ToString("0.0") ?? "N/A"}°C";
}
private static SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
public static async Task SafeExecuteAsync(Func<Task> action)
{
await semaphore.WaitAsync();
try
{
await action();
}
finally
{
semaphore.Release();
}
}
}
public static class FuncoesMatematicas
{
public static double Map(double valor, double deMin, double deMax, double paraMin, double paraMax)
{
return paraMin + (valor - deMin) * (paraMax - paraMin) / (deMax - deMin);
}
public static double ConvertDegreesToRadians(double degrees)
{
double radians = (Math.PI / 180) * degrees;
return (radians);
}
public static double CalcularAlturaTriangulo(double a, double b, double c)
{
// Verifica se os lados formam um triângulo válido
if (a + b <= c || a + c <= b || b + c <= a)
{
return 0;
}
// Calcule a área do triângulo usando a fórmula de Herão
double s = (a + b + c) / 2.0; // Semiperímetro
double area = Math.Sqrt(s * (s - a) * (s - b) * (s - c));
// Calcule a altura em relação à base c
double altura = (2 * area) / c;
return altura;
}
public static double CalcularMediana(List<double> numbers)
{
numbers.Sort();
int count = numbers.Count;
if (count % 2 == 0)
{
// Se count é par, a mediana é a média dos dois elementos do meio
double middle1 = numbers[count / 2 - 1];
double middle2 = numbers[count / 2];
return (middle1 + middle2) / 2.0;
}
else
{
// Se count é ímpar, a mediana é o elemento do meio
return numbers[count / 2];
}
}
public static double CalcularModa(List<double> numbers)
{
return numbers.GroupBy(n => n)
.OrderByDescending(g => g.Count())
.First()
.Key;
}
/*public static double CalcularTemperatura(double leitura, double offset)
{
double Vs = 3.3; // TENSÃO DE SAIDA DO ESP32
double R1 = 10000; //RESISTOR UTILIZADO NO DIVISOR DE TENSÃO
double Beta = 3950; // VALOR DE BETA
double To = 298.15; // VALOR EM KELVIN REFERENTE A 25° CELSIUS
double Ro = 10000;
double adcMax = 1024.0;
double Vout, Rt = 0;
double T, Tc, Tf, adc = 0;
//CALCULOS PARA CONVERSÃO DA LEITURA RECEBIDA PELO ESP32 EM TEMPERATURA EM °C
Vout = (leitura * Vs / adcMax) + offset;
Rt = R1 * Vout / (Vs - Vout);
T = 1 / (1 / To + Math.Log(Rt / Ro) / Beta);
Tc = T - 273.15;
Tf = Tc * 9 / 5 + 32;
Tc = Math.Round(Tc, 2);
return Tc;
}*/
public static double CalcularTemperatura(double leitura, double offset)
{
double Vs = 5.0; // TENSÃO DE SAÍDA DO ESP32
double Beta = 3950; // VALOR DE BETA
double To = 298.15; // VALOR EM KELVIN REFERENTE A 25° CELSIUS
double Ro = 10000; // RESISTÊNCIA DO NTC A 25°C
double adcMax = 4096.0;
double Vout, Rt = 0;
double T, Tc, Tf, adc = 0;
// CALCULOS PARA CONVERSÃO DA LEITURA RECEBIDA PELO ESP32 EM TEMPERATURA EM °C
Vout = (leitura * Vs / adcMax) + offset;
Rt = Ro * (Vs / Vout - 1);
T = 1 / (1 / To + Math.Log(Rt / Ro) / Beta);
Tc = T - 273.15;
Tf = Tc * 9 / 5 + 32;
Tc = Math.Round(Tc, 2);
return Tc;
}
public static bool ValorEstaEntre(double valorAtual, double valorComparar, double margem)
{
if (valorAtual <= (valorComparar + margem) && valorAtual >= (valorComparar - margem))
{
return true;
}
return false;
}
// Função personalizada Clamp
public static double Clamp(double valor, double minimo, double maximo)
{
if (valor < minimo) return minimo;
if (valor > maximo) return maximo;
return valor;
}
public static double CalculaVelocidadeRPM(double RPM)
{
double VelocidadeInstantanea = Math.Round((Math.PI * VariaveisEquipamento.DiametroRoda * 60 * RPM) / 1000, 2); // Km/h
return VelocidadeInstantanea;
}
public static double CalculaRPMVelocidade(double Velocidade)
{
double RPM = Math.Round((Velocidade * 1000) / (Math.PI * VariaveisEquipamento.DiametroRoda * 60), 2);
return RPM;
}
public static double ConverteKmhParaMs(double Velocidade)
{
return Velocidade / 3.6;
}
}
}