重写IOC容器绑定逻辑

This commit is contained in:
fengjiayi
2024-09-30 16:36:55 +08:00
parent 55f0e2f70d
commit c80f0f85cd
14 changed files with 530 additions and 301 deletions

View File

@@ -1,7 +1,8 @@
using IoTClient.Clients.PLC;
using IoTClient;
using IoTClient.Clients.PLC;
using IoTClient.Enums;
using Net461DllTest.Enums;
using Net461DllTest.Signal;
using Net461DllTest.Utils;
using Serein.Library.Attributes;
using Serein.Library.NodeFlow.Tool;
using System;
@@ -13,7 +14,7 @@ namespace Net461DllTest.Device
/// 官方文档如果没有主动Open则会每次读写操作的时候自动打开自动和关闭连接这样会使读写效率大大减低。所以建议手动Open和Close。
/// </summary>
[AutoRegister]
public class SiemensPlcDevice : ChannelFlowTrigger<OrderSignal>
public class SiemensPlcDevice : ChannelFlowTrigger<CommandSignal>
{
public SiemensClient Client { get; set; }
@@ -69,4 +70,224 @@ namespace Net461DllTest.Device
}
}
/// <summary>
/// PLC方法
/// </summary>
public static class PlcExtension
{
public static DataTypeEnum ToDataTypeEnum(this PlcVarInfo varInfo)
{
Type dataType = varInfo.DataType;
DataTypeEnum plcDataType;
switch (dataType)
{
case Type _ when dataType == typeof(string):
plcDataType = DataTypeEnum.String;
break;
case Type _ when dataType == typeof(char):
plcDataType = DataTypeEnum.String;
break;
case Type _ when dataType == typeof(bool):
plcDataType = DataTypeEnum.Bool;
break;
case Type _ when dataType == typeof(float):
plcDataType = DataTypeEnum.Float;
break;
case Type _ when dataType == typeof(double):
plcDataType = DataTypeEnum.Double;
break;
case Type _ when dataType == typeof(byte):
plcDataType = DataTypeEnum.Byte;
break;
case Type _ when dataType == typeof(short):
plcDataType = DataTypeEnum.Int16;
break;
case Type _ when dataType == typeof(ushort):
plcDataType = DataTypeEnum.UInt16;
break;
case Type _ when dataType == typeof(int):
plcDataType = DataTypeEnum.Int32;
break;
case Type _ when dataType == typeof(uint):
plcDataType = DataTypeEnum.UInt32;
break;
case Type _ when dataType == typeof(long):
plcDataType = DataTypeEnum.Int64;
break;
case Type _ when dataType == typeof(ulong):
plcDataType = DataTypeEnum.UInt64;
break;
default:
plcDataType = DataTypeEnum.None;
break;
}
return plcDataType;
}
/// <summary>
/// 读取设备的值
/// </summary>
/// <param name="client"></param>
/// <param name="varInfo"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static object ReadToPlcValue(this SiemensClient client, PlcVarInfo varInfo)
{
Type dataType = varInfo.DataType;
object resultvalue;
if (dataType == typeof(string))
{
var result = client.ReadString(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(char))
{
var result = client.ReadString(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(bool))
{
var result = client.ReadBoolean(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(float))
{
var result = client.ReadFloat(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(double))
{
var result = client.ReadDouble(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(byte))
{
var result = client.ReadByte(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(short))
{
var result = client.ReadInt16(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(ushort))
{
var result = client.ReadUInt16(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(int))
{
var result = client.ReadInt32(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(uint))
{
var result = client.ReadUInt32(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(long))
{
var result = client.ReadInt64(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else if (dataType == typeof(ulong))
{
var result = client.ReadUInt64(varInfo.VarAddress);
if (!result.IsSucceed) throw new Exception(result.Err);
resultvalue = result.Value;
}
else
{
resultvalue = default;
}
return resultvalue;
}
public static void WriteToPlcValue(this SiemensClient client, PlcVarInfo varInfo, object value)
{
if (client == null) throw new ArgumentNullException("client");
Type dataType = varInfo.DataType;
Result result = null;
if (dataType == typeof(string))
{
result = client.Write(varInfo.VarAddress, value.ToString());
}
else if (dataType == typeof(char))
{
result = client.Write(varInfo.VarAddress, value.ToString());
}
else if (dataType == typeof(bool))
{
var @bool = bool.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @bool);
}
else if (dataType == typeof(float))
{
var @float = float.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @float);
}
else if (dataType == typeof(double))
{
var @double = double.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @double);
}
else if (dataType == typeof(byte))
{
var @byte = byte.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @byte);
}
else if (dataType == typeof(short))
{
var @short = short.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @short);
}
else if (dataType == typeof(ushort))
{
var @ushort = ushort.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @ushort);
}
else if (dataType == typeof(int))
{
var @int = int.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @int);
}
else if (dataType == typeof(uint))
{
var @uint = uint.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @uint);
}
else if (dataType == typeof(long))
{
var @long = long.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @long);
}
else if (dataType == typeof(ulong))
{
var @ulong = ulong.Parse(value.ToString());
result = client.Write(varInfo.VarAddress, @ulong);
}
if (result is null)
{
throw new Exception($"未定义的数据类型");
}
if (!result.IsSucceed)
{
throw new Exception(result.Err);
}
}
}
}

View File

@@ -17,18 +17,35 @@ namespace Net461DllTest.Enums
public enum PlcVarEnum
{
None,
/// <summary>
/// 车位号
/// </summary>
[PlcValue(typeof(short), "V100", VarType.Writable)]
SpaceNum,
/// <summary>
/// 上位机指令
/// </summary>
[PlcValue(typeof(short), "V102", VarType.Writable)]
CmdForPLC,
/// <summary>
/// PLC当前存取车位号
/// </summary>
[PlcValue(typeof(short), "V110", VarType.ReadOnly)]
DoingSpaceNum,
/// <summary>
/// 下位机状态
/// </summary>
[PlcValue(typeof(short), "V112", VarType.ReadOnly)]
PLCState,
/// <summary>
/// 门1正常待机车位号存车完成地面车位0
/// </summary>
[PlcValue(typeof(short), "V114", VarType.ReadOnly)]
Door1CurSpaceNum,
/// <summary>
/// 门2正常待机车位号存车完成地面车位0
@@ -73,6 +90,17 @@ namespace Net461DllTest.Enums
[PlcValue(typeof(bool), "V207.4", VarType.ReadOnly)]
IsDoor2ClosedDone,
/// <summary>
/// 通道1是否有车
/// </summary>
[PlcValue(typeof(bool), "V284.7", VarType.ReadOnly)]
HasCarInTone1,
/// <summary>
/// 通道2是否有车
/// </summary>
[PlcValue(typeof(bool), "V286.7", VarType.ReadOnly)]
HasCarInTone2,
/// <summary>
/// 下位机异常代码
@@ -80,6 +108,12 @@ namespace Net461DllTest.Enums
[PlcValue(typeof(short), "V2", VarType.ReadOnly)]
ErrorCode,
/// <summary>
/// 2层以上的空板是否在待机
/// </summary>
[PlcValue(typeof(bool), "V200.7", VarType.ReadOnly)]
IsOver2FlowStanded,
/// <summary>
/// 1号门指示灯
/// </summary>

View File

@@ -29,30 +29,43 @@ namespace Net461DllTest.LogicControl
public PlcLogicControl(SiemensPlcDevice MyPlc)
{
this.MyPlc = MyPlc;
}
#region 退
[NodeAction(NodeType.Init)] // Init 初始化事件,流程启动时执行
public void Init(IDynamicContext context)
{
// // 注册控制器
context.Env.IOC.Run<IRouter>(router => {
router.RegisterController(typeof(ApiController));
});
context.Env.IOC.Register<IRouter, Router>();
context.Env.IOC.Register<WebServer>();
}
[NodeAction(NodeType.Loading)] // Loading 初始化完成已注入依赖项,可以开始逻辑上的操作
public void Loading(IDynamicContext context)
{
context.Env.IOC.Run<WebServer>((web) =>
{
web.Start("http://*:8089/"); // 开启 Web 服务
// 注册控制器
context.Env.IOC.Run<IRouter, WebServer>((router, web) => {
try
{
router.RegisterController(typeof(CommandController));
web.Start("http://*:8089/"); // 开启 Web 服务
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
});
}
[NodeAction(NodeType.Exit)] // 流程结束时自动执行
public void Exit(IDynamicContext context)
{
context.Env.IOC.Run<WebServer>((web) =>
{
web?.Stop(); // 关闭 Web 服务
});
MyPlc.ResetDevice();
MyPlc.CancelAllTasks();
}
@@ -62,7 +75,7 @@ namespace Net461DllTest.LogicControl
#region
[NodeAction(NodeType.Flipflop, "等待信号触发", ReturnType = typeof(int))]
public async Task<IFlipflopContext> WaitTask(OrderSignal order = OrderSignal.Command_1)
public async Task<IFlipflopContext> WaitTask(CommandSignal order = CommandSignal.Command_1)
{
try
{
@@ -113,7 +126,6 @@ namespace Net461DllTest.LogicControl
return MyPlc;
}
[NodeAction(NodeType.Action, "设置PLC状态")]
public SiemensPlcDevice SetState(PlcState state = PlcState.PowerOff)
{
@@ -129,14 +141,12 @@ namespace Net461DllTest.LogicControl
Console.WriteLine($"PLC尚未初始化");
return MyPlc;
}
}
// [BindConvertor(typeof(PlcVarEnum), typeof(PlcVarConvertor))]
[NodeAction(NodeType.Action, "PLC获取变量")]
public object ReadVar(PlcVarEnum plcVarEnum)
{
var varInfo = Convertor(plcVarEnum);
var varInfo = ToVarInfo(plcVarEnum);
var result = MyPlc.Read(varInfo);
Console.WriteLine($"获取变量成功:({varInfo})\t result = {result}");
return result;
@@ -145,7 +155,7 @@ namespace Net461DllTest.LogicControl
[NodeAction(NodeType.Action, "PLC写入变量")]
public SiemensPlcDevice WriteVar2(object value, PlcVarEnum plcVarEnum)
{
var varInfo = Convertor(plcVarEnum);
var varInfo = ToVarInfo(plcVarEnum);
if (MyPlc.State == PlcState.Runing)
{
if (varInfo.IsProtected)
@@ -165,9 +175,12 @@ namespace Net461DllTest.LogicControl
return MyPlc;
}
private readonly Dictionary<PlcVarEnum, PlcVarInfo> VarInfoDict;
public PlcVarInfo Convertor(PlcVarEnum plcVarEnum)
/// <summary>
/// 缓存变量信息
/// </summary>
private readonly Dictionary<PlcVarEnum, PlcVarInfo> VarInfoDict = new Dictionary<PlcVarEnum, PlcVarInfo>();
private PlcVarInfo ToVarInfo(PlcVarEnum plcVarEnum)
{
if (VarInfoDict.ContainsKey(plcVarEnum))
{
@@ -187,28 +200,6 @@ namespace Net461DllTest.LogicControl
return plcValue;
}
/// <summary>
/// 转换器,用于将枚举转为自定义特性中的数据
/// </summary>
//public class PlcVarConvertor: IEnumConvertor<PlcVarEnum, PlcVarInfo>
//{
// public PlcVarInfo Convertor(PlcVarEnum plcVarValue)
// {
// if (plcVarValue == PlcVarEnum.None)
// {
// throw new Exception("非预期枚举值");
// }
// var plcValue = EnumHelper.GetBoundValue<PlcVarEnum, PlcValueAttribute, PlcVarInfo>(plcVarValue, attr => attr.PlcInfo)
// ?? throw new Exception($"获取变量异常:{plcVarValue}没有标记PlcValueAttribute");
// if (string.IsNullOrEmpty(plcValue.VarAddress))
// {
// throw new Exception($"获取变量异常:{plcVarValue},变量地址为空");
// }
// return plcValue;
// }
//}
#endregion
}
}

View File

@@ -10,19 +10,23 @@ using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Net461DllTest.LogicControl
{
namespace Net461DllTest.LogicControl
{
/// <summary>
/// 视图管理
/// </summary>
[AutoRegister]
public class ViewManagement
{
private List<Form> forms = new List<Form>();
/// <summary>
/// 打开窗口
/// </summary>
/// <param name="form">要打开的窗口类型</param>
/// <param name="isTop">是否置顶</param>
public void OpenView(Form form, bool isTop)
{
form.FormClosing += (s, e) =>
{
// 关闭窗体时执行一些关于逻辑层的操作
};
form.TopMost = isTop;
form.Show();
forms.Add(form);
@@ -36,8 +40,6 @@ namespace Net461DllTest.LogicControl
f.Dispose();
this.forms.Remove(f);
}
}
}

View File

@@ -68,7 +68,7 @@
<Compile Include="LogicControl\ParkingLogicControl.cs" />
<Compile Include="LogicControl\ViewLogicControl.cs" />
<Compile Include="Enums\FromValue.cs" />
<Compile Include="Signal\OrderSignal.cs" />
<Compile Include="Signal\CommandSignal_1.cs" />
<Compile Include="Signal\PLCVarSignal.cs" />
<Compile Include="Utils\ToValue.cs" />
<Compile Include="ViewModel\FromWorkBenchViewModel.cs" />
@@ -84,7 +84,7 @@
<Compile Include="View\TestFormView.Designer.cs">
<DependentUpon>TestFormView.cs</DependentUpon>
</Compile>
<Compile Include="Web\ApiController.cs" />
<Compile Include="Web\CommandController_1.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\DynamicControl\SereinFlow\Library.Framework\Serein.Library.Framework.csproj">

View File

@@ -1,6 +1,6 @@
namespace Net461DllTest.Signal
{
public enum OrderSignal
public enum CommandSignal
{
Command_1,
Command_2,

View File

@@ -0,0 +1,15 @@
namespace Net461DllTest.Signal
{
public enum CommandSignal
{
Command_1,
Command_2,
Command_3,
Command_4,
Command_5,
Command_6,
Command_7,
Command_8,
Command_9,
}
}

View File

@@ -21,7 +21,7 @@ namespace Net461DllTest
public FromWorkBenchView(IFlowEnvironment env)
{
ViewModel = env.IOC.Instantiate<FromWorkBenchViewModel>();
ViewModel = env.IOC.Instantiate<FromWorkBenchViewModel>(); // 创建对象并注入依赖项
InitializeComponent();
Init();
}
@@ -29,7 +29,7 @@ namespace Net461DllTest
public void Init()
{
listBox1.Items.Clear();
var enumValues = Enum.GetValues(typeof(OrderSignal)).Cast<OrderSignal>();
var enumValues = Enum.GetValues(typeof(CommandSignal)).Cast<CommandSignal>();
foreach (var value in enumValues)
{
listBox1.Items.Add(value.ToString());
@@ -49,7 +49,7 @@ namespace Net461DllTest
}
string type = listBox1.SelectedItem.ToString();
if (!string.IsNullOrEmpty(type) && Enum.TryParse(type, out OrderSignal signal) && Enum.IsDefined(typeof(OrderSignal), signal))
if (!string.IsNullOrEmpty(type) && Enum.TryParse(type, out CommandSignal signal) && Enum.IsDefined(typeof(CommandSignal), signal))
{
Console.WriteLine($"Trigger : {type}");
ViewModel.Trigger(signal,textBoxSpaceNum.Text);

View File

@@ -24,7 +24,7 @@ namespace Net461DllTest.ViewModel
return Device?.ToString();
}
public void Trigger(OrderSignal signal,string spcaeNumber)
public void Trigger(CommandSignal signal,string spcaeNumber)
{
_ = Task.Run(() =>
{

View File

@@ -0,0 +1,47 @@
using Net461DllTest.Device;
using Net461DllTest.Signal;
using Serein.Library.Attributes;
using Serein.Library.Web;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Net461DllTest.Web
{
[AutoHosting]
public class CommandController : ControllerBase
{
private SiemensPlcDevice PlcDevice;
public CommandController(SiemensPlcDevice PlcDevice)
{
this.PlcDevice = PlcDevice;
}
/*
* 类型 POST
* url : http://127.0.0.1:8089/command/trigger?command=
* body [JSON]
*
* {
* "value":0,
* }
*
*/
[WebApi(API.POST)]
public dynamic Trigger([Url] string command, int value)
{
if (Enum.TryParse(command, out CommandSignal signal) && Enum.IsDefined(typeof(CommandSignal), signal))
{
Console.WriteLine($"外部触发 {signal} 信号,信号内容 {value} ");
PlcDevice.TriggerSignal(signal, value);// 通过 Web Api 模拟外部输入信号
return new { state = "succeed" };
}
return new { state = "fail" };
}
}
}

View File

@@ -11,15 +11,25 @@ using System.Threading.Tasks;
namespace Net461DllTest.Web
{
[AutoHosting]
public class ApiController : ControllerBase
public class CommandController : ControllerBase
{
[AutoInjection]
public SiemensPlcDevice PlcDevice { get; set; }
/*
* POST
* url : http://127.0.0.1:8089/command/trigger?command=
* body [JSON]
*
* {
* "value":0,
* }
*
*/
[WebApi(API.POST)]
public dynamic Trigger([Url] string type, int value)
public dynamic Trigger([Url] string command, int value)
{
if (Enum.TryParse(type, out OrderSignal signal) && Enum.IsDefined(typeof(OrderSignal), signal))
if (Enum.TryParse(command, out CommandSignal signal) && Enum.IsDefined(typeof(CommandSignal), signal))
{
Console.WriteLine($"外部触发 {signal} 信号,信号内容 {value} ");
PlcDevice.TriggerSignal(signal, value);// 通过 Web Api 模拟外部输入信号