242 lines
8.4 KiB
C#
242 lines
8.4 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using RobotNet10.RobotApp.Client.Shared.Devices;
|
|
using RobotNet10.RobotApp.Devices;
|
|
using RobotNet10.Shared;
|
|
|
|
namespace RobotNet10.RobotApp.Hubs;
|
|
|
|
/// <summary>
|
|
/// SignalR Hub cho ModbusTCP device - cung cấp real-time Modbus data
|
|
/// </summary>
|
|
[Authorize]
|
|
public class ModbusTcpHub(IDeviceProvider deviceProvider) : Hub
|
|
{
|
|
/// <summary>
|
|
/// Lấy thông tin device (DeviceName) theo device ID
|
|
/// </summary>
|
|
public async Task<DeviceInfoDto?> GetDeviceInfo(string deviceId)
|
|
{
|
|
var device = deviceProvider.GetDevice(deviceId);
|
|
if (device is not IModbusTcpDevice)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new DeviceInfoDto
|
|
{
|
|
DeviceId = device.DeviceId,
|
|
DeviceName = device.DeviceName
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Lấy tất cả dữ liệu Modbus theo device ID
|
|
/// </summary>
|
|
public async Task<ModbusTcpData?> GetModbusData(string deviceId)
|
|
{
|
|
var device = deviceProvider.GetDevice(deviceId);
|
|
if (device is not IModbusTcpDevice modbusDevice)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return MapToDto(modbusDevice);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ghi một coil theo device ID
|
|
/// </summary>
|
|
/// <param name="deviceId">Device ID</param>
|
|
/// <param name="address">Địa chỉ coil</param>
|
|
/// <param name="value">Giá trị cần ghi (true/false)</param>
|
|
/// <returns>True nếu thành công, false nếu thất bại</returns>
|
|
public async Task<bool> WriteCoil(string deviceId, ushort address, bool value)
|
|
{
|
|
var device = deviceProvider.GetDevice(deviceId);
|
|
if (device is not IModbusTcpDevice modbusDevice)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
await modbusDevice.WriteCoilAsync(address, value);
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Map IModbusTcpDevice sang ModbusTcpDataDto
|
|
/// </summary>
|
|
private static ModbusTcpData MapToDto(IModbusTcpDevice modbusDevice)
|
|
{
|
|
var dto = new ModbusTcpData
|
|
{
|
|
IpAddress = modbusDevice.IpAddress,
|
|
Port = modbusDevice.Port,
|
|
SlaveId = modbusDevice.SlaveId,
|
|
IsConnected = modbusDevice.IsConnected
|
|
};
|
|
|
|
var holdingRegisters = new List<ModbusRangeData>();
|
|
// Lấy Holding Registers
|
|
foreach (var range in modbusDevice.HoldingRegisterRanges)
|
|
{
|
|
try
|
|
{
|
|
var values = modbusDevice.ReadHoldingRegisters(range.StartAddress, range.Quantity);
|
|
var rangeData = new ModbusRangeData
|
|
{
|
|
StartAddress = range.StartAddress,
|
|
Quantity = range.Quantity,
|
|
Name = range.Name,
|
|
ChildrenNames = range.ChildrenNames == null ? [] : [.. range.ChildrenNames]
|
|
};
|
|
|
|
var modbusValues = new List<ModbusValue>();
|
|
for (ushort i = 0; i < values.Length; i++)
|
|
{
|
|
var address = (ushort)(range.StartAddress + i);
|
|
var childName = (range.ChildrenNames != null && i < range.ChildrenNames.Length) ? range.ChildrenNames[i] : "";
|
|
modbusValues.Add(new ModbusValue
|
|
{
|
|
Address = address,
|
|
Index = i,
|
|
Value = values[i],
|
|
Name = childName
|
|
});
|
|
}
|
|
rangeData.Values = [.. modbusValues];
|
|
holdingRegisters.Add(rangeData);
|
|
}
|
|
catch
|
|
{
|
|
// Skip range nếu không đọc được
|
|
}
|
|
}
|
|
dto.HoldingRegisters = [.. holdingRegisters];
|
|
|
|
|
|
var inputRegisters = new List<ModbusRangeData>();
|
|
// Lấy Input Registers
|
|
foreach (var range in modbusDevice.InputRegisterRanges)
|
|
{
|
|
try
|
|
{
|
|
var values = modbusDevice.ReadInputRegisters(range.StartAddress, range.Quantity);
|
|
var rangeData = new ModbusRangeData
|
|
{
|
|
StartAddress = range.StartAddress,
|
|
Quantity = range.Quantity,
|
|
Name = range.Name,
|
|
ChildrenNames = range.ChildrenNames == null ? [] : [.. range.ChildrenNames]
|
|
};
|
|
|
|
var modbusValues = new List<ModbusValue>();
|
|
for (ushort i = 0; i < values.Length; i++)
|
|
{
|
|
var address = (ushort)(range.StartAddress + i);
|
|
var childName = (range.ChildrenNames != null && i < range.ChildrenNames.Length) ? range.ChildrenNames[i] : "";
|
|
modbusValues.Add(new ModbusValue
|
|
{
|
|
Address = address,
|
|
Index = i,
|
|
Value = values[i],
|
|
Name = childName
|
|
});
|
|
}
|
|
rangeData.Values = [.. modbusValues];
|
|
|
|
inputRegisters.Add(rangeData);
|
|
}
|
|
catch
|
|
{
|
|
// Skip range nếu không đọc được
|
|
}
|
|
}
|
|
dto.InputRegisters = [.. inputRegisters];
|
|
|
|
// Lấy Coils
|
|
var coils = new List<ModbusRangeData>();
|
|
foreach (var range in modbusDevice.CoilRanges)
|
|
{
|
|
try
|
|
{
|
|
var values = modbusDevice.ReadCoils(range.StartAddress, range.Quantity);
|
|
var rangeData = new ModbusRangeData
|
|
{
|
|
StartAddress = range.StartAddress,
|
|
Quantity = range.Quantity,
|
|
Name = range.Name,
|
|
ChildrenNames = range.ChildrenNames ?? []
|
|
};
|
|
|
|
var modbusValues = new List<ModbusBoolValue>();
|
|
for (ushort i = 0; i < values.Length; i++)
|
|
{
|
|
var address = (ushort)(range.StartAddress + i);
|
|
var childName = (range.ChildrenNames != null && i < range.ChildrenNames.Length) ? range.ChildrenNames[i] : "";
|
|
modbusValues.Add(new ModbusBoolValue
|
|
{
|
|
Address = address,
|
|
Index = i,
|
|
Value = values[i],
|
|
Name = childName
|
|
});
|
|
}
|
|
rangeData.BoolValues = [.. modbusValues];
|
|
coils.Add(rangeData);
|
|
}
|
|
catch
|
|
{
|
|
// Skip range nếu không đọc được
|
|
}
|
|
}
|
|
dto.Coils = [.. coils];
|
|
|
|
// Lấy Discrete Inputs
|
|
var inputs = new List<ModbusRangeData>();
|
|
foreach (var range in modbusDevice.DiscreteInputRanges)
|
|
{
|
|
try
|
|
{
|
|
var values = modbusDevice.ReadDiscreteInputs(range.StartAddress, range.Quantity);
|
|
var rangeData = new ModbusRangeData
|
|
{
|
|
StartAddress = range.StartAddress,
|
|
Quantity = range.Quantity,
|
|
Name = range.Name,
|
|
ChildrenNames = range.ChildrenNames ?? []
|
|
};
|
|
|
|
var modbusValues = new List<ModbusBoolValue>();
|
|
for (ushort i = 0; i < values.Length; i++)
|
|
{
|
|
var address = (ushort)(range.StartAddress + i);
|
|
var childName = (range.ChildrenNames != null && i < range.ChildrenNames.Length) ? range.ChildrenNames[i] : "";
|
|
modbusValues.Add(new ModbusBoolValue
|
|
{
|
|
Address = address,
|
|
Index = i,
|
|
Value = values[i],
|
|
Name = childName
|
|
});
|
|
}
|
|
rangeData.BoolValues = [.. modbusValues];
|
|
inputs.Add(rangeData);
|
|
}
|
|
catch
|
|
{
|
|
// Skip range nếu không đọc được
|
|
}
|
|
}
|
|
dto.DiscreteInputs = [.. inputs];
|
|
return dto;
|
|
}
|
|
}
|