#region copyright
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权(除特别声明外的代码)归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
// 使用文档:https://diego2098.gitee.io/thingsgateway-docs/
// QQ群:605534569
//------------------------------------------------------------------------------
#endregion
using SqlSugar;
using System.Collections.Concurrent;
using ThingsGateway.Foundation.Adapter.Modbus;
using ThingsGateway.Foundation.Demo;
using ThingsGateway.Foundation.Extension;
using ThingsGateway.Foundation.Extension.ConcurrentQueue;
using ThingsGateway.Foundation.Extension.String;
namespace ThingsGateway.Plugin.Modbus;
///
///
///
public class ModbusSerialServer : UpLoadBase
{
private readonly ModbusSerialServerProperty _driverPropertys = new();
private readonly ModbusTcpServerVariableProperty _variablePropertys = new();
private Dictionary _modbusTags;
private ConcurrentQueue<(string, DeviceVariableRunTime)> _modbusVariableDict = new();
private ThingsGateway.Foundation.Adapter.Modbus.ModbusSerialServer _plc;
///
public override Type DriverDebugUIType => typeof(ModbusSerialServerDebugPage);
///
public override DriverPropertyBase DriverPropertys => _driverPropertys;
public override Type DriverUIType => null;
///
public override VariablePropertyBase VariablePropertys => _variablePropertys;
///
protected override IReadWrite _readWrite => _plc;
///
protected override void Dispose(bool disposing)
{
_modbusTags?.Values?.ToList()?.ForEach(a => a.VariableValueChange -= VariableValueChange);
_modbusTags?.Clear();
_modbusVariableDict?.Clear();
base.Dispose(disposing);
}
///
protected override void Init(ISenderClient client = null)
{
var service = new SerialSession();
FoundataionConfig.SetSerialProperty(new()
{
PortName = _driverPropertys.PortName,
BaudRate = _driverPropertys.BaudRate,
DataBits = _driverPropertys.DataBits,
Parity = _driverPropertys.Parity,
StopBits = _driverPropertys.StopBits,
})
;
service = new SerialSession();
((SerialSession)service).Setup(FoundataionConfig);
//载入配置
_plc = new(service)
{
DataFormat = _driverPropertys.DataFormat,
Station = _driverPropertys.Station,
CacheTimeout = _driverPropertys.CacheTimeout,
MulStation = _driverPropertys.MulStation
};
var tags = CurrentDevice.DeviceVariableRunTimes
.Where(b => !string.IsNullOrEmpty(
b.GetPropertyValue(DeviceId, nameof(_variablePropertys.ServiceAddress)).Value))
.ToList();
tags.ForEach(a =>
{
a.VariableValueChange += VariableValueChange;
VariableValueChange(a);
});
_modbusTags = tags.ToDictionary(a =>
{
ModbusAddress address = ModbusAddress.ParseFrom(
a.GetPropertyValue(DeviceId,
nameof(_variablePropertys.ServiceAddress)).Value, _driverPropertys.Station);
return address;
});
_plc.OnWriteData += OnWriteData;
_plc.Connect(CancellationToken.None);
}
protected override async Task ProtectedExecuteAsync(CancellationToken cancellationToken)
{
//获取设备连接状态
if (IsConnected())
{
//更新设备活动时间
CurrentDevice.SetDeviceStatus(DateTimeExtensions.CurrentDateTime, 0);
}
else
{
CurrentDevice.SetDeviceStatus(DateTimeExtensions.CurrentDateTime, 999);
}
var list = _modbusVariableDict.ToListWithDequeue();
foreach (var item in list)
{
if (cancellationToken.IsCancellationRequested)
break;
var type = item.Item2.GetPropertyValue(CurrentDevice.Id, nameof(ModbusTcpServerVariableProperty.ModbusType)).Value;
if (Enum.TryParse(type, out DataTypeEnum result))
{
await _plc.WriteAsync(item.Item1, item.Item2.Value?.ToString(), 1, result, cancellationToken);
}
else
{
await _plc.WriteAsync(item.Item1, item.Item2.Value?.ToString(), 1, item.Item2.DataTypeEnum, cancellationToken);
}
}
await Delay(_driverPropertys.CycleInterval, cancellationToken);
}
///
/// RPC写入
///
///
///
///
///
///
private async Task OnWriteData(ModbusAddress address, byte[] bytes, IThingsGatewayBitConverter thingsGatewayBitConverter, ISenderClient client)
{
try
{
var tag = _modbusTags.FirstOrDefault(a => a.Key?.AddressStart == address.AddressStart && a.Key?.Station == address.Station && a.Key?.ReadFunction == address.ReadFunction);
if (tag.Value == null) return OperResult.CreateSuccessResult();
var enable = tag.Value.GetPropertyValue(DeviceId, nameof(_variablePropertys.VariableRpcEnable)).Value.ToBool(false) && _driverPropertys.DeviceRpcEnable;
if (!enable) return new OperResult("不允许写入");
var type = tag.Value.GetPropertyValue(DeviceId, nameof(ModbusTcpServerVariableProperty.ModbusType)).Value;
var addressStr = tag.Value.GetPropertyValue(DeviceId, nameof(ModbusTcpServerVariableProperty.ServiceAddress)).Value;
var bitConverter = ByteTransformUtil.GetTransByAddress(ref addressStr, thingsGatewayBitConverter);
if (Enum.TryParse(type, out DataTypeEnum result))
{
var result1 = await RpcSingletonService.InvokeDeviceMethodAsync($"{nameof(ModbusTcpServer)}-{CurrentDevice.Name}-{$"{client}"}",
new Dictionary
{
{
tag.Value.Name,
bitConverter.GetDataFormBytes( bytes,result).ToString()
},
}
);
return result1.FirstOrDefault().Value;
}
else
{
var result1 = await RpcSingletonService.InvokeDeviceMethodAsync($"{nameof(ModbusTcpServer)}-{CurrentDevice.Name}-{$"{client}"}",
new Dictionary
{
{
tag.Value.Name,
bitConverter.GetDataFormBytes( bytes,result).ToString()
},
}
);
return result1.FirstOrDefault().Value;
}
}
catch (Exception ex)
{
return new OperResult(ex);
}
}
///
private void VariableValueChange(DeviceVariableRunTime collectVariableRunTime)
{
if (!CurrentDevice.KeepRun)
return;
var address = collectVariableRunTime.GetPropertyValue(DeviceId, nameof(_variablePropertys.ServiceAddress)).Value;
if (address != null && collectVariableRunTime.Value != null)
{
_modbusVariableDict?.Enqueue((address, collectVariableRunTime));
}
}
}