146 lines
5.1 KiB
C#
146 lines
5.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using static Emgu.CV.ML.KNearest;
|
|
|
|
namespace AgroBase.Services
|
|
{
|
|
public class ModbusService
|
|
{
|
|
public static byte[] Crc16(byte[] data)
|
|
{
|
|
ushort crc = 0xFFFF;
|
|
foreach (byte pos in data)
|
|
{
|
|
crc ^= pos;
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if ((crc & 1) != 0)
|
|
{
|
|
crc >>= 1;
|
|
crc ^= 0xA001;
|
|
}
|
|
else
|
|
{
|
|
crc >>= 1;
|
|
}
|
|
}
|
|
}
|
|
return new byte[] { (byte)crc, (byte)(crc >> 8) };
|
|
}
|
|
|
|
public static bool VerifyChecksum(byte[] bytes)
|
|
{
|
|
if (bytes.Length < 2) return false;
|
|
|
|
// Extrai o CRC recebido dos últimos dois bytes da mensagem
|
|
byte[] receivedCrc = new byte[] { bytes[bytes.Length - 2], bytes[bytes.Length - 1] };
|
|
|
|
// Extrai os dados da mensagem sem o CRC
|
|
byte[] data = new byte[bytes.Length - 2];
|
|
Array.Copy(bytes, data, bytes.Length - 2);
|
|
|
|
// Calcula o CRC dos dados
|
|
byte[] computedCrc = Crc16(data);
|
|
|
|
// Verifica se o CRC calculado é igual ao CRC recebido
|
|
return receivedCrc[0] == computedCrc[0] && receivedCrc[1] == computedCrc[1];
|
|
}
|
|
|
|
public static byte[] HexStringToByteArray(string hex)
|
|
{
|
|
int NumberChars = hex.Length;
|
|
byte[] bytes = new byte[NumberChars / 2];
|
|
for (int i = 0; i < NumberChars; i += 2)
|
|
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
|
|
return bytes;
|
|
}
|
|
|
|
public static int ByteArrayToDecimal(byte[] bytes)
|
|
{
|
|
if (bytes == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(bytes));
|
|
}
|
|
|
|
switch (bytes.Length)
|
|
{
|
|
case 2:
|
|
// Converter 2 bytes para short e depois para decimal
|
|
int shortValue = BitConverter.ToInt32(bytes, 0);
|
|
return shortValue;
|
|
|
|
case 4:
|
|
// Converter 4 bytes para int e depois para decimal
|
|
int intValue = BitConverter.ToInt32(bytes, 0);
|
|
return intValue;
|
|
|
|
default:
|
|
throw new ArgumentException("O array de bytes deve ter 2 ou 4 elementos.");
|
|
}
|
|
}
|
|
|
|
public static byte[] ComandoSetParametro(byte slaveAddress, ModbusParametrosModel Parametro, float valor)
|
|
{
|
|
Parametro.UltimaRequisicao = DateTime.Now;
|
|
|
|
// Convertendo o valor para o formato correto (LSB = 0.01)
|
|
int valorInt = (int)(valor * Parametro.Escala); // Convertendo para inteiro conforme a resolução
|
|
byte functionCode = Parametro.FuncaoSet;
|
|
ushort registerAddress = Parametro.Registro;
|
|
|
|
// Construindo o comando
|
|
List<byte> command = new List<byte>();
|
|
command.Add(slaveAddress);
|
|
command.Add(functionCode);
|
|
command.AddRange(BitConverter.GetBytes(registerAddress).Reverse()); // Little endian
|
|
command.AddRange(BitConverter.GetBytes((ushort)valorInt).Reverse()); // Little endian
|
|
|
|
byte[] crc = Crc16(command.ToArray()); // Supondo que você tenha a implementação do CRC16
|
|
command.AddRange(crc);
|
|
|
|
return command.ToArray();
|
|
}
|
|
|
|
public static byte[] ComandoGetParametro(byte slaveAddress, ModbusParametrosModel Parametro)
|
|
{
|
|
Parametro.UltimaRequisicao = DateTime.Now;
|
|
|
|
byte functionCode = Parametro.FuncaoGet;
|
|
ushort registerAddress = Parametro.Registro;
|
|
ushort numberOfRegisters = Parametro.N_Registros; // Lendo apenas um registro
|
|
|
|
// Construindo o comando
|
|
List<byte> command = new List<byte>();
|
|
command.Add(slaveAddress);
|
|
command.Add(functionCode);
|
|
command.AddRange(BitConverter.GetBytes(registerAddress).Reverse()); // Big endian
|
|
command.AddRange(BitConverter.GetBytes(numberOfRegisters).Reverse()); // Big endian
|
|
|
|
byte[] crc = Crc16(command.ToArray()); // Supondo que você tenha a implementação do CRC16
|
|
command.AddRange(crc);
|
|
|
|
return command.ToArray();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public class ModbusParametrosModel
|
|
{
|
|
public DateTime UltimaRequisicao { get; set; } = DateTime.MaxValue;
|
|
public string Descricao { get; set; }
|
|
public string Chave { get; set; }
|
|
public byte FuncaoGet { get; set; }
|
|
public byte FuncaoSet { get; set; }
|
|
public byte Registro { get; set; }
|
|
public byte N_Registros { get; set; }
|
|
public bool LeituraLoop { get; set; }
|
|
public bool LeituraGeral { get; set; }
|
|
public double Escala { get; set; }
|
|
public byte[] Valor { get; set; }
|
|
}
|
|
}
|