mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-02 15:50:47 +08:00
Delete Net462DllTest directory
需要重写
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
using Serein.Library;
|
||||
|
||||
namespace Net462DllTest.Signal
|
||||
{
|
||||
/*public enum FromValue
|
||||
{
|
||||
[BindValue(typeof(FromWorkBenchView))]
|
||||
FromWorkBenchView,
|
||||
[BindValue(typeof(TestFormView))]
|
||||
TestFormView,
|
||||
}*/
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Net462DllTest.Enums
|
||||
{
|
||||
public enum PlcState
|
||||
{
|
||||
/// <summary>
|
||||
/// 关机
|
||||
/// </summary>
|
||||
PowerOff,
|
||||
/// <summary>
|
||||
/// 正在运行
|
||||
/// </summary>
|
||||
Runing,
|
||||
/// <summary>
|
||||
/// 发生异常
|
||||
/// </summary>
|
||||
Error,
|
||||
/// <summary>
|
||||
/// 维护中
|
||||
/// </summary>
|
||||
Maintenance,
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
using IoTClient.Enums;
|
||||
using Net462DllTest.Signal;
|
||||
using static Net462DllTest.Signal.PlcVarInfo;
|
||||
|
||||
namespace Net462DllTest.Enums
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// PLC变量信息
|
||||
/// </summary>
|
||||
public enum PlcVarName
|
||||
{
|
||||
/// <summary>
|
||||
/// 车位号
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V100", OnNotificationType.OnChanged)]
|
||||
SpaceNum,
|
||||
|
||||
/// <summary>
|
||||
/// 上位机指令
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V102", OnNotificationType.OnChanged)]
|
||||
CmdForPLC,
|
||||
|
||||
/// <summary>
|
||||
/// PLC当前存取车位号
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V110", OnNotificationType.OnChanged)]
|
||||
DoingSpaceNum,
|
||||
|
||||
/// <summary>
|
||||
/// 下位机状态
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V112", OnNotificationType.OnChanged)]
|
||||
PLCState,
|
||||
|
||||
/// <summary>
|
||||
/// 门1正常待机车位号,存车完成地面车位0
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V114", OnNotificationType.OnChanged)]
|
||||
Door1CurSpaceNum,
|
||||
|
||||
/// <summary>
|
||||
/// 门2正常待机车位号,存车完成地面车位0
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V124", OnNotificationType.OnChanged)]
|
||||
Door2CurSpaceNum,
|
||||
|
||||
/// <summary>
|
||||
/// 下位机运行模式
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V116", OnNotificationType.OnChanged)]
|
||||
PLCRunMode,
|
||||
|
||||
/// <summary>
|
||||
/// 执行的门号
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V104", OnNotificationType.OnChanged)]
|
||||
DoorVar,
|
||||
|
||||
/// <summary>
|
||||
/// 门1是否开到位
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "V207.0", OnNotificationType.OnChanged)]
|
||||
IsDoor1OpenDone,
|
||||
|
||||
/// <summary>
|
||||
/// 门1是否关到位
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "V207.1", OnNotificationType.OnChanged)]
|
||||
IsDoor1ClosedDone,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 门2是否开到位
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "V207.3", OnNotificationType.OnChanged)]
|
||||
IsDoor2OpenDone,
|
||||
|
||||
/// <summary>
|
||||
/// 门2是否关到位
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "V207.4", OnNotificationType.OnChanged)]
|
||||
IsDoor2ClosedDone,
|
||||
|
||||
/// <summary>
|
||||
/// 通道1是否有车
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "V284.7", OnNotificationType.OnChanged)]
|
||||
HasCarInTone1,
|
||||
|
||||
/// <summary>
|
||||
/// 通道2是否有车
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "V286.7", OnNotificationType.OnChanged)]
|
||||
HasCarInTone2,
|
||||
|
||||
/// <summary>
|
||||
/// 下位机异常代码
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Int16, "V2", OnNotificationType.OnChanged)]
|
||||
ErrorCode,
|
||||
|
||||
/// <summary>
|
||||
/// 2层以上的空板是否在待机
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "V200.7", OnNotificationType.OnChanged)]
|
||||
IsOver2FlowStanded,
|
||||
|
||||
/// <summary>
|
||||
/// 1号门指示灯
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "Q17.0", OnNotificationType.OnChanged)]
|
||||
Gate1Light,
|
||||
|
||||
/// <summary>
|
||||
/// 2号门指示灯
|
||||
/// </summary>
|
||||
[PlcVarInfo(DataTypeEnum.Bool, "Q17.3", OnNotificationType.OnChanged)]
|
||||
Gate2Light,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using Net462DllTest.Trigger;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Net462DllTest.LogicControl
|
||||
{
|
||||
|
||||
public enum ParkingCommand
|
||||
{
|
||||
GetPparkingSpace,
|
||||
}
|
||||
|
||||
[AutoRegister]
|
||||
[DynamicFlow("[Parking]")]
|
||||
public class ParkingLogicControl
|
||||
{
|
||||
private readonly PrakingDevice PrakingDevice;
|
||||
|
||||
public ParkingLogicControl(PrakingDevice PrakingDevice)
|
||||
{
|
||||
this.PrakingDevice = PrakingDevice;
|
||||
}
|
||||
|
||||
|
||||
[NodeAction(NodeType.Flipflop, "等待车位调取命令")]
|
||||
public async Task<IFlipflopContext<string>> GetPparkingSpace(ParkingCommand parkingCommand = ParkingCommand.GetPparkingSpace)
|
||||
{
|
||||
var result = await PrakingDevice.WaitTriggerAsync<string>(parkingCommand);
|
||||
await Console.Out.WriteLineAsync("收到命令:调取车位,车位号" + result.Value);
|
||||
return new FlipflopContext<string>(FlipflopStateType.Succeed, result.Value);
|
||||
}
|
||||
|
||||
|
||||
[NodeAction(NodeType.Action, "调取指定车位")]
|
||||
public async Task Storage(string spaceNum = "101")
|
||||
{
|
||||
if (await PrakingDevice.InvokeTriggerAsync(ParkingCommand.GetPparkingSpace, spaceNum))
|
||||
{
|
||||
Console.WriteLine("发送命令成功:调取车位" + spaceNum);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("发送命令失败:调取车位" + spaceNum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
using IoTClient.Common.Enums;
|
||||
using Net462DllTest.Enums;
|
||||
using Net462DllTest.Model;
|
||||
using Net462DllTest.Trigger;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Net462DllTest.LogicControl
|
||||
{
|
||||
[AutoRegister]
|
||||
[DynamicFlow("[SiemensPlc]")]
|
||||
public class PlcLogicControl
|
||||
{
|
||||
public Guid HandleGuid { get; } = new Guid();
|
||||
|
||||
private readonly SiemensPlcDevice MyPlc;
|
||||
private readonly PlcVarModelDataProxy plcVarModelDataProxy;
|
||||
|
||||
public PlcLogicControl(SiemensPlcDevice MyPlc,
|
||||
PlcVarModelDataProxy plcVarModelDataProxy)
|
||||
{
|
||||
this.MyPlc = MyPlc;
|
||||
this.plcVarModelDataProxy = plcVarModelDataProxy;
|
||||
}
|
||||
|
||||
#region 初始化
|
||||
[NodeAction(NodeType.Loading)] // Loading 初始化完成已注入依赖项,可以开始逻辑上的操作
|
||||
public void Loading(IFlowContext context)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
[NodeAction(NodeType.Exit)] // 流程结束时自动执行
|
||||
public void Exit(IFlowContext context)
|
||||
{
|
||||
MyPlc.Close();
|
||||
MyPlc.CancelAllTrigger();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 触发器节点
|
||||
|
||||
[NodeAction(NodeType.Flipflop, "等待变量更新")]
|
||||
public async Task<IFlipflopContext<object>> WaitTask(PlcVarName varName = PlcVarName.ErrorCode)
|
||||
{
|
||||
try
|
||||
{
|
||||
var triggerData = await MyPlc.WaitTriggerAsync<object>(varName);
|
||||
await Console.Out.WriteLineAsync($"PLC变量触发器[{varName}]传递数据:{triggerData}");
|
||||
return new FlipflopContext<object>(FlipflopStateType.Succeed, triggerData);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 动作节点
|
||||
|
||||
[NodeAction(NodeType.Action, "等待")]
|
||||
public async Task Delay(int ms = 5000)
|
||||
{
|
||||
await Console.Out.WriteLineAsync("开始等待");
|
||||
await Task.Delay(ms);
|
||||
await Console.Out.WriteLineAsync("不再等待");
|
||||
|
||||
}
|
||||
|
||||
|
||||
[NodeAction(NodeType.Action, "PLC初始化")]
|
||||
public SiemensPlcDevice PlcInit(SiemensVersion version = SiemensVersion.None,
|
||||
string ip = "192.168.10.100",
|
||||
int port = 102)
|
||||
{
|
||||
//MyPlc.Model.Set(PlcVarName.DoorVar,(Int16)1);
|
||||
//MyPlc.Model.Get(PlcVarName.DoorVar);
|
||||
if (MyPlc.Client is null)
|
||||
{
|
||||
try
|
||||
{
|
||||
MyPlc.Init(version, ip, port);
|
||||
Console.WriteLine($"西门子PLC初始化成功[{version},{ip}:{port}]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"西门子PLC[{version},{ip}:{port}]初始化异常:{ex.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine( $"西门子PLC已经初始化[{version},{ip}:{port}]");
|
||||
}
|
||||
return MyPlc;
|
||||
}
|
||||
|
||||
[NodeAction(NodeType.Action, "设置PLC状态")]
|
||||
public SiemensPlcDevice SetState(PlcState state = PlcState.PowerOff)
|
||||
{
|
||||
var oldState = MyPlc.State;
|
||||
MyPlc.State = state;
|
||||
Console.WriteLine($"PLC状态从[{oldState}]转为[{state}]");
|
||||
return MyPlc;
|
||||
}
|
||||
|
||||
|
||||
[NodeAction(NodeType.Action, "PLC获取变量")]
|
||||
public object ReadVar(PlcVarName varName)
|
||||
{
|
||||
var result = MyPlc.Read(varName);
|
||||
Console.WriteLine($"获取变量成功:({varName})\t result = {result}");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
[NodeAction(NodeType.Action, "PLC写入变量")]
|
||||
public SiemensPlcDevice WriteVar(object value, PlcVarName varName)
|
||||
{
|
||||
MyPlc.Write(varName, value); // 新数据
|
||||
return MyPlc;
|
||||
}
|
||||
|
||||
[NodeAction(NodeType.Action, "批量读取")]
|
||||
public PlcVarModelDataProxy BatchReadVar()
|
||||
{
|
||||
//MyPlc.BatchRefresh();
|
||||
return plcVarModelDataProxy;
|
||||
}
|
||||
|
||||
|
||||
[NodeAction(NodeType.Action, "开启定时刷新")]
|
||||
public void OpenTimedRefresh()
|
||||
{
|
||||
Task.Run(async () => await MyPlc.OpenTimedRefreshAsync());
|
||||
}
|
||||
|
||||
[NodeAction(NodeType.Action, "关闭定时刷新")]
|
||||
public void CloseTimedRefresh()
|
||||
{
|
||||
MyPlc.CloseTimedRefresh();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using Serein.Library;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Net462DllTest.Properties
|
||||
{
|
||||
/*
|
||||
理想的项目架构:
|
||||
|
||||
每一种功能拆分为新的项目
|
||||
|
||||
FlowEnv - LoginControl:
|
||||
|
||||
|
||||
LoginControl
|
||||
↙ ↘
|
||||
(View-Interaction) (Node-Interaction)
|
||||
↓ ↕
|
||||
View ←→ ViewModel ←→ Trigger ← SingleEnum
|
||||
↓ ↓ ↖
|
||||
↓ ↓ ↖
|
||||
Node →→→ Model → Event(OnDataChanged)
|
||||
|
||||
|
||||
视图驱动触发器,触发器驱动数据。
|
||||
数据驱动触发器,触发器驱动视图。
|
||||
|
||||
所以,这个结构≈事件驱动。
|
||||
|
||||
|
||||
动态的配置事件触发的原因、过程与结果。
|
||||
|
||||
*/
|
||||
|
||||
public class My
|
||||
{
|
||||
public void Run()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
using Net462DllTest.Enums;
|
||||
using Serein.Library;
|
||||
using System;
|
||||
|
||||
namespace Net462DllTest.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// PLC变量
|
||||
/// </summary>
|
||||
[AutoRegister]
|
||||
public class PlcVarModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 车位号
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.SpaceNum)]
|
||||
public Int16 SpaceNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上位机指令
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.CmdForPLC)]
|
||||
public Int16 CmdForPLC { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// PLC当前存取车位号
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.DoingSpaceNum)]
|
||||
public Int16 DoingSpaceNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下位机状态
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.PLCState)]
|
||||
public Int16 PLCState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门1正常待机车位号,存车完成地面车位0
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.Door1CurSpaceNum)]
|
||||
public Int16 Door1CurSpaceNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门2正常待机车位号,存车完成地面车位0
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.Door2CurSpaceNum)]
|
||||
public Int16 Door2CurSpaceNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下位机运行模式
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.PLCRunMode)]
|
||||
public Int16 PLCRunMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行的门号
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.DoorVar)]
|
||||
public Int16 DoorVar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门1是否开到位
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.IsDoor1OpenDone)]
|
||||
public bool IsDoor1OpenDone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门1是否关到位
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.IsDoor1ClosedDone)]
|
||||
public bool IsDoor1ClosedDone { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 门2是否开到位
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.IsDoor2OpenDone)]
|
||||
public bool IsDoor2OpenDone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门2是否关到位
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.IsDoor2ClosedDone)]
|
||||
public bool IsDoor2ClosedDone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道1是否有车
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.HasCarInTone1)]
|
||||
public bool HasCarInTone1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道2是否有车
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.HasCarInTone2)]
|
||||
public bool HasCarInTone2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下位机异常代码
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.ErrorCode)]
|
||||
public Int16 ErrorCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 2层以上的空板是否在待机
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.IsOver2FlowStanded)]
|
||||
public bool IsOver2FlowStanded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 1号门指示灯
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.Gate1Light)]
|
||||
public bool Gate1Light { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 2号门指示灯
|
||||
/// </summary>
|
||||
[BindValue(PlcVarName.Gate2Light)]
|
||||
public bool Gate2Light { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 数据代理,防止View修改
|
||||
/// </summary>
|
||||
[AutoRegister]
|
||||
public class PlcVarModelDataProxy
|
||||
{
|
||||
private readonly PlcVarModel plcVarModel;
|
||||
public PlcVarModelDataProxy(PlcVarModel plcVarModel)
|
||||
{
|
||||
this.plcVarModel = plcVarModel;
|
||||
}
|
||||
/// <summary>
|
||||
/// 车位号
|
||||
/// </summary>
|
||||
public Int16 SpaceNum { get => plcVarModel.SpaceNum; }
|
||||
|
||||
/// <summary>
|
||||
/// 上位机指令
|
||||
/// </summary>
|
||||
public Int16 CmdForPLC { get => plcVarModel.CmdForPLC; }
|
||||
|
||||
/// <summary>
|
||||
/// PLC当前存取车位号
|
||||
/// </summary>
|
||||
public Int16 DoingSpaceNum { get => plcVarModel.DoingSpaceNum; }
|
||||
|
||||
/// <summary>
|
||||
/// 下位机状态
|
||||
/// </summary>
|
||||
public Int16 PLCState { get => plcVarModel.PLCState; }
|
||||
|
||||
/// <summary>
|
||||
/// 门1正常待机车位号,存车完成地面车位0
|
||||
/// </summary>
|
||||
public Int16 Door1CurSpaceNum { get => plcVarModel.Door1CurSpaceNum; }
|
||||
|
||||
/// <summary>
|
||||
/// 门2正常待机车位号,存车完成地面车位0
|
||||
/// </summary>
|
||||
public Int16 Door2CurSpaceNum { get => plcVarModel.Door2CurSpaceNum; }
|
||||
|
||||
/// <summary>
|
||||
/// 下位机运行模式
|
||||
/// </summary>
|
||||
public Int16 PLCRunMode { get => plcVarModel.PLCRunMode; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行的门号
|
||||
/// </summary>
|
||||
public Int16 DoorVar { get => plcVarModel.DoorVar; }
|
||||
|
||||
/// <summary>
|
||||
/// 门1是否开到位
|
||||
/// </summary>
|
||||
public bool IsDoor1OpenDone { get => plcVarModel.IsDoor1OpenDone; }
|
||||
|
||||
/// <summary>
|
||||
/// 门1是否关到位
|
||||
/// </summary>
|
||||
public bool IsDoor1ClosedDone { get => plcVarModel.IsDoor1ClosedDone; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 门2是否开到位
|
||||
/// </summary>
|
||||
public bool IsDoor2OpenDone { get => plcVarModel.IsDoor2OpenDone; }
|
||||
|
||||
/// <summary>
|
||||
/// 门2是否关到位
|
||||
/// </summary>
|
||||
public bool IsDoor2ClosedDone { get => plcVarModel.IsDoor2ClosedDone; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道1是否有车
|
||||
/// </summary>
|
||||
public bool HasCarInTone1 { get => plcVarModel.HasCarInTone1; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道2是否有车
|
||||
/// </summary>
|
||||
public bool HasCarInTone2 { get => plcVarModel.HasCarInTone2; }
|
||||
|
||||
/// <summary>
|
||||
/// 下位机异常代码
|
||||
/// </summary>
|
||||
public Int16 ErrorCode { get => plcVarModel.ErrorCode; }
|
||||
|
||||
/// <summary>
|
||||
/// 2层以上的空板是否在待机
|
||||
/// </summary>
|
||||
public bool IsOver2FlowStanded { get => plcVarModel.IsOver2FlowStanded; }
|
||||
|
||||
/// <summary>
|
||||
/// 1号门指示灯
|
||||
/// </summary>
|
||||
public bool Gate1Light { get => plcVarModel.Gate1Light; }
|
||||
|
||||
/// <summary>
|
||||
/// 2号门指示灯
|
||||
/// </summary>
|
||||
public bool Gate2Light { get => plcVarModel.Gate2Light; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E40EE629-1A38-4011-88E3-9AD036869987}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Net462DllTest</RootNamespace>
|
||||
<AssemblyName>Net462DllTest</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="IoTClient, Version=1.0.40.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\IoTClient.1.0.40\lib\netstandard2.0\IoTClient.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Ports, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.IO.Ports.4.6.0\lib\net461\System.IO.Ports.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Model\PlcVarModel.cs" />
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="Trigger\SiemensPlcDevice.cs" />
|
||||
<Compile Include="Trigger\PrakingDevice.cs" />
|
||||
<Compile Include="Enums\PlcState.cs" />
|
||||
<Compile Include="Enums\PlcVarName.cs" />
|
||||
<Compile Include="LogicControl\PlcLogicControl.cs" />
|
||||
<Compile Include="LogicControl\ParkingLogicControl.cs" />
|
||||
<Compile Include="Enums\FromValue.cs" />
|
||||
<Compile Include="Signal\CommandSignal.cs" />
|
||||
<Compile Include="Signal\PLCVarSignal.cs" />
|
||||
<Compile Include="Trigger\ViewManagement.cs" />
|
||||
<Compile Include="Utils\GSModel.cs" />
|
||||
<Compile Include="Utils\RelayCommand.cs" />
|
||||
<Compile Include="Web\FlowController.cs" />
|
||||
<Compile Include="Web\PlcSocketService.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Library\Serein.Library.csproj">
|
||||
<Project>{5e19d0f2-913a-4d1c-a6f8-1e1227baa0e3}</Project>
|
||||
<Name>Serein.Library</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace Net462DllTest.Signal
|
||||
{
|
||||
public enum CommandSignal
|
||||
{
|
||||
Command_1,
|
||||
Command_2,
|
||||
Command_3,
|
||||
Command_4,
|
||||
Command_5,
|
||||
Command_6,
|
||||
Command_7,
|
||||
Command_8,
|
||||
Command_9,
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
using IoTClient.Enums;
|
||||
using Net462DllTest.Enums;
|
||||
using System;
|
||||
using static Net462DllTest.Signal.PlcVarInfo;
|
||||
|
||||
namespace Net462DllTest.Signal
|
||||
{
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class PlcVarInfoAttribute : Attribute
|
||||
{
|
||||
public PlcVarInfo Info { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dateType">数据类型</param>
|
||||
/// <param name="address">变量地址</param>
|
||||
/// <param name="notificationType">通知行为类型</param>
|
||||
/// <param name="isReadOnly">是否只读</param>
|
||||
/// <param name="isTimingRead">是否定时刷新</param>
|
||||
/// <param name="interval">刷新间隔(ms)</param>
|
||||
public PlcVarInfoAttribute(DataTypeEnum dateType,
|
||||
string address,
|
||||
OnNotificationType notificationType,
|
||||
bool isReadOnly = false,
|
||||
bool isTimingRead = true,
|
||||
int interval = 1000
|
||||
)
|
||||
{
|
||||
Info = new PlcVarInfo()
|
||||
{
|
||||
DataType = dateType,
|
||||
IsReadOnly = isReadOnly,
|
||||
Address = address,
|
||||
Interval = interval,
|
||||
IsTimingRead= isTimingRead,
|
||||
NotificationType = notificationType,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class PlcVarInfo
|
||||
{
|
||||
public enum OnNotificationType
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷新时通知(每次写入Model后都会触发相应的触发器)
|
||||
/// </summary>
|
||||
OnRefresh,
|
||||
/// <summary>
|
||||
/// 改变时才通知(与Model对应数据不一致时才会触发相应的触发器)
|
||||
/// </summary>
|
||||
OnChanged,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 变量类型
|
||||
/// </summary>
|
||||
public PlcVarName Name { get; set; }
|
||||
/// <summary>
|
||||
/// 数据类型
|
||||
/// </summary>
|
||||
public DataTypeEnum DataType { get; set; }
|
||||
/// <summary>
|
||||
/// 变量地址
|
||||
/// </summary>
|
||||
public string Address { get; set; }
|
||||
/// <summary>
|
||||
/// 变量是否只读
|
||||
/// </summary>
|
||||
public bool IsReadOnly { get; set; }
|
||||
/// <summary>
|
||||
/// 是否定时刷新
|
||||
/// </summary>
|
||||
public bool IsTimingRead { get; set; }
|
||||
/// <summary>
|
||||
/// 刷新间隔(ms)
|
||||
/// </summary>
|
||||
public int Interval { get; set; } = 100; // 100ms
|
||||
public OnNotificationType NotificationType { get; set; } = OnNotificationType.OnChanged;
|
||||
public override string ToString()
|
||||
{
|
||||
if (IsTimingRead)
|
||||
{
|
||||
return $"数据:{Name},类型:{DataType},地址:{Address},只读:{IsReadOnly},自动刷新:{IsTimingRead},刷新间隔:{Interval}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"数据:{Name},类型:{DataType},地址:{Address},只读:{IsReadOnly}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using Net462DllTest.LogicControl;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Utils;
|
||||
|
||||
namespace Net462DllTest.Trigger
|
||||
{
|
||||
[AutoRegister]
|
||||
public class PrakingDevice : TaskFlowTrigger<ParkingCommand>
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,463 +0,0 @@
|
||||
using IoTClient;
|
||||
using IoTClient.Clients.PLC;
|
||||
using IoTClient.Common.Enums;
|
||||
using IoTClient.Enums;
|
||||
using Net462DllTest.Enums;
|
||||
using Net462DllTest.Model;
|
||||
using Net462DllTest.Signal;
|
||||
using Net462DllTest.Utils;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Utils;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Net462DllTest.Trigger
|
||||
{
|
||||
|
||||
|
||||
[AutoRegister]
|
||||
public class SiemensPlcDevice : TaskFlowTrigger<PlcVarName>
|
||||
{
|
||||
public SiemensClient Client { get; set; }
|
||||
public SiemensVersion Version { get; set; }
|
||||
public string IP { get; set; } = "127.0.0.1";
|
||||
public int Port { get; set; } = 102;
|
||||
public PlcState State { get; set; } = PlcState.PowerOff;
|
||||
public bool IsTimedRefresh { get; set; } = false; // 是否定时刷新
|
||||
public IGSModel<PlcVarName, PlcVarModel> Model { get; }
|
||||
|
||||
|
||||
private readonly object _lockObj = new object(); // 防止多次初始化读取任务
|
||||
private readonly ConcurrentBag<Task> TimedRefreshTask = new ConcurrentBag<Task>(); // 定时读取任务
|
||||
private readonly ConcurrentBag<PlcVarInfo> VarInfos = new ConcurrentBag<PlcVarInfo>(); // 所有变量信息
|
||||
private readonly ConcurrentBag<PlcVarInfo> OnRefreshs = new ConcurrentBag<PlcVarInfo>(); // 数据变更后需要通知触发器的变量信息
|
||||
private readonly ConcurrentBag<PlcVarInfo> OnChangeds = new ConcurrentBag<PlcVarInfo>(); // 读取读取后需要通知触发器的变量信息
|
||||
|
||||
public SiemensPlcDevice(PlcVarModel model)
|
||||
{
|
||||
this.Model = new GSModel<PlcVarName, PlcVarModel>(model);
|
||||
LoadVarInfos();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载变量信息
|
||||
/// </summary>
|
||||
private void LoadVarInfos()
|
||||
{
|
||||
foreach (var property in typeof(PlcVarModel).GetProperties())
|
||||
{
|
||||
var attribute = property.GetCustomAttribute<BindValueAttribute>();
|
||||
if (attribute?.Value is PlcVarName varName)
|
||||
{
|
||||
var varInfo = varName.ToVarInfo();
|
||||
VarInfos.Add(varInfo);
|
||||
if (varInfo.IsTimingRead) // 是否定时刷新
|
||||
{
|
||||
switch (varInfo.NotificationType)
|
||||
{
|
||||
case PlcVarInfo.OnNotificationType.OnRefresh:
|
||||
OnRefreshs.Add(varInfo); // 变量读取时通知触发器的变量
|
||||
break;
|
||||
case PlcVarInfo.OnNotificationType.OnChanged:
|
||||
OnChangeds.Add(varInfo); // 变量变更时才需要通知触发器的变量
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Init(SiemensVersion version, string ip, int port)
|
||||
{
|
||||
Client = new SiemensClient(version, ip, port);
|
||||
Version = version;
|
||||
IP = ip;
|
||||
Port = port;
|
||||
Client.Open();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Client?.Close();
|
||||
Client = null;
|
||||
}
|
||||
|
||||
public void Write(PlcVarName varName, object value)
|
||||
{
|
||||
var varInfo = varName.ToVarInfo();
|
||||
if (this.State == PlcState.Runing)
|
||||
{
|
||||
if (varInfo.IsReadOnly)
|
||||
{
|
||||
throw new Exception($"PLC变量{varInfo}当前禁止写入");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Client.WriteVar(varInfo, value); // 尝试写入PLC
|
||||
Model.Set(varName, value);
|
||||
Console.WriteLine($"PLC变量{varInfo}写入数据:{value}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"PLC处于非预期状态{this.State}");
|
||||
}
|
||||
}
|
||||
|
||||
public object Read(PlcVarName varName)
|
||||
{
|
||||
var varInfo = varName.ToVarInfo();
|
||||
var result = Client.ReadVar(varInfo);// 尝试读取数据
|
||||
Model.Set(varName, result); // 缓存读取的数据
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public void BatchRefresh()
|
||||
{
|
||||
foreach(var varInfo in VarInfos)
|
||||
{
|
||||
Read(varInfo.Name); // 无条件批量读取
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 开启定时批量读取任务
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task OpenTimedRefreshAsync()
|
||||
{
|
||||
if (TimedRefreshTask.IsEmpty)
|
||||
{
|
||||
InitTimedRefreshTask();
|
||||
}
|
||||
IsTimedRefresh = true;
|
||||
await Task.WhenAll(TimedRefreshTask.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭定时任务
|
||||
/// </summary>
|
||||
public void CloseTimedRefresh() => IsTimedRefresh = false;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化定时刷新任务
|
||||
/// </summary>
|
||||
public void InitTimedRefreshTask()
|
||||
{
|
||||
Console.WriteLine("开始初始化刷新任务");
|
||||
lock (_lockObj)
|
||||
{
|
||||
foreach (var varInfo in OnChangeds)
|
||||
{
|
||||
Console.WriteLine($"添加监视任务(OnChanged):{varInfo.Name}");
|
||||
ScheduleTask(varInfo);
|
||||
}
|
||||
foreach (var varInfo in OnRefreshs)
|
||||
{
|
||||
Console.WriteLine($"添加监视任务(OnRefresh):{varInfo.Name}");
|
||||
ScheduleTask(varInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时读取PLC变量,并刷新Model的值
|
||||
/// </summary>
|
||||
/// <param name="varInfo"></param>
|
||||
private void ScheduleTask(PlcVarInfo varInfo)
|
||||
{
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
var signal = varInfo.Name;
|
||||
object oldData;
|
||||
object newData;
|
||||
bool isNotification;
|
||||
while (true)
|
||||
{
|
||||
await Task.Delay(varInfo.Interval);
|
||||
if (!IsTimedRefresh || Client is null) break;
|
||||
|
||||
oldData = Model.Get(signal); // 暂存旧数据
|
||||
newData = Read(signal); // 获取新数据
|
||||
if (varInfo.NotificationType == PlcVarInfo.OnNotificationType.OnRefresh)
|
||||
{
|
||||
isNotification = true; // 无条件触发通知
|
||||
}
|
||||
else
|
||||
{
|
||||
isNotification = !oldData.Equals(newData); // 变更时才会触发通知
|
||||
}
|
||||
|
||||
if (isNotification)
|
||||
{
|
||||
Console.WriteLine($"VarName: {signal}\t\tOld Data: {oldData}\tNew Data: {newData}");
|
||||
await InvokeTriggerAsync(signal, newData);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
TimedRefreshTask.Add(task);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"西门子Plc[{this.Version}-{this.IP}:{this.Port}]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 拓展方法
|
||||
/// </summary>
|
||||
public static class MyPlcExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存变量信息
|
||||
/// </summary>
|
||||
private static readonly Dictionary<PlcVarName, PlcVarInfo> VarInfoDict = new Dictionary<PlcVarName, PlcVarInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// 获取变量信息
|
||||
/// </summary>
|
||||
/// <param name="plcVarEnum"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static PlcVarInfo ToVarInfo(this PlcVarName plcVarEnum)
|
||||
{
|
||||
if (VarInfoDict.ContainsKey(plcVarEnum))
|
||||
{
|
||||
return VarInfoDict[plcVarEnum];
|
||||
}
|
||||
var plcValue = EnumHelper.GetAttributeValue<PlcVarName, PlcVarInfoAttribute, PlcVarInfo>(plcVarEnum, attr => attr.Info)
|
||||
?? throw new Exception($"获取变量异常:{plcVarEnum},没有标记PlcValueAttribute");
|
||||
if (string.IsNullOrEmpty(plcValue.Address))
|
||||
{
|
||||
throw new Exception($"获取变量异常:{plcVarEnum},变量地址为空");
|
||||
}
|
||||
VarInfoDict.Add(plcVarEnum, plcValue);
|
||||
plcValue.Name = plcVarEnum;
|
||||
return plcValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取PLC
|
||||
/// </summary>
|
||||
public static object ReadVar(this SiemensClient client, PlcVarInfo varInfo)
|
||||
{
|
||||
if (client is null)
|
||||
{
|
||||
throw new ArgumentNullException($"PLC尚未初始化");
|
||||
}
|
||||
object resultvalue;
|
||||
switch (varInfo.DataType)
|
||||
{
|
||||
case DataTypeEnum.String:
|
||||
var resultString = client.ReadString(varInfo.Address);
|
||||
if (!resultString.IsSucceed) throw new Exception(resultString.Err);
|
||||
resultvalue = resultString.Value;
|
||||
break;
|
||||
case DataTypeEnum.Bool:
|
||||
var resultBool = client.ReadBoolean(varInfo.Address);
|
||||
if (!resultBool.IsSucceed) throw new Exception(resultBool.Err);
|
||||
resultvalue = resultBool.Value;
|
||||
break;
|
||||
case DataTypeEnum.Float:
|
||||
var resultFloat = client.ReadFloat(varInfo.Address);
|
||||
if (!resultFloat.IsSucceed) throw new Exception(resultFloat.Err);
|
||||
resultvalue = resultFloat.Value;
|
||||
break;
|
||||
case DataTypeEnum.Double:
|
||||
var resultDouble = client.ReadDouble(varInfo.Address);
|
||||
if (!resultDouble.IsSucceed) throw new Exception(resultDouble.Err);
|
||||
resultvalue = resultDouble.Value;
|
||||
break;
|
||||
case DataTypeEnum.Byte:
|
||||
var resultByte = client.ReadByte(varInfo.Address);
|
||||
if (!resultByte.IsSucceed) throw new Exception(resultByte.Err);
|
||||
resultvalue = resultByte.Value;
|
||||
break;
|
||||
case DataTypeEnum.Int16:
|
||||
var resultInt16 = client.ReadInt16(varInfo.Address);
|
||||
if (!resultInt16.IsSucceed) throw new Exception(resultInt16.Err);
|
||||
resultvalue = resultInt16.Value;
|
||||
break;
|
||||
case DataTypeEnum.UInt16:
|
||||
var resultUint16 = client.ReadUInt16(varInfo.Address);
|
||||
if (!resultUint16.IsSucceed) throw new Exception(resultUint16.Err);
|
||||
resultvalue = resultUint16.Value;
|
||||
break;
|
||||
case DataTypeEnum.Int32:
|
||||
var resultInt32 = client.ReadInt32(varInfo.Address);
|
||||
if (!resultInt32.IsSucceed) throw new Exception(resultInt32.Err);
|
||||
resultvalue = resultInt32.Value;
|
||||
break;
|
||||
case DataTypeEnum.UInt32:
|
||||
var resultUInt32 = client.ReadUInt32(varInfo.Address);
|
||||
if (!resultUInt32.IsSucceed) throw new Exception(resultUInt32.Err);
|
||||
resultvalue = resultUInt32.Value;
|
||||
break;
|
||||
case DataTypeEnum.Int64:
|
||||
var resultInt64 = client.ReadInt64(varInfo.Address);
|
||||
if (!resultInt64.IsSucceed) throw new Exception(resultInt64.Err);
|
||||
resultvalue = resultInt64.Value;
|
||||
break;
|
||||
case DataTypeEnum.UInt64:
|
||||
var resultUInt64 = client.ReadUInt64(varInfo.Address);
|
||||
if (!resultUInt64.IsSucceed) throw new Exception(resultUInt64.Err);
|
||||
resultvalue = resultUInt64.Value;
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"变量为指定数据类型,或是非预期的数据类型{varInfo}");
|
||||
}
|
||||
return resultvalue;
|
||||
}
|
||||
/// <summary>
|
||||
/// 转换数据类型,写入PLC
|
||||
/// </summary>
|
||||
public static object WriteVar(this SiemensClient client, PlcVarInfo varInfo, object value)
|
||||
{
|
||||
if (client is null)
|
||||
{
|
||||
throw new ArgumentNullException($"PLC尚未初始化");
|
||||
}
|
||||
DataTypeEnum dataType = varInfo.DataType;
|
||||
object convertValue;
|
||||
Result result;
|
||||
switch (dataType)
|
||||
{
|
||||
case DataTypeEnum.String:
|
||||
var @string = value.ToString();
|
||||
convertValue = @string;
|
||||
result = client.Write(varInfo.Address, @string);
|
||||
break;
|
||||
case DataTypeEnum.Bool:
|
||||
var @bool = bool.Parse(value.ToString());
|
||||
convertValue = @bool;
|
||||
result = client.Write(varInfo.Address, @bool);
|
||||
break;
|
||||
case DataTypeEnum.Float:
|
||||
var @float = float.Parse(value.ToString());
|
||||
convertValue = @float;
|
||||
result = client.Write(varInfo.Address, @float);
|
||||
break;
|
||||
case DataTypeEnum.Double:
|
||||
var @double = double.Parse(value.ToString());
|
||||
convertValue = @double;
|
||||
result = client.Write(varInfo.Address, @double);
|
||||
break;
|
||||
case DataTypeEnum.Byte:
|
||||
var @byte = byte.Parse(value.ToString());
|
||||
convertValue = @byte;
|
||||
result = client.Write(varInfo.Address, @byte);
|
||||
break;
|
||||
case DataTypeEnum.Int16:
|
||||
var @short = short.Parse(value.ToString());
|
||||
convertValue = @short;
|
||||
result = client.Write(varInfo.Address, @short);
|
||||
break;
|
||||
case DataTypeEnum.UInt16:
|
||||
var @ushort = ushort.Parse(value.ToString());
|
||||
convertValue = @ushort;
|
||||
result = client.Write(varInfo.Address, @ushort);
|
||||
break;
|
||||
case DataTypeEnum.Int32:
|
||||
var @int = int.Parse(value.ToString());
|
||||
convertValue = @int;
|
||||
result = client.Write(varInfo.Address, @int);
|
||||
break;
|
||||
case DataTypeEnum.UInt32:
|
||||
var @uint = uint.Parse(value.ToString());
|
||||
convertValue = @uint;
|
||||
result = client.Write(varInfo.Address, @uint);
|
||||
break;
|
||||
case DataTypeEnum.Int64:
|
||||
var @long = long.Parse(value.ToString());
|
||||
convertValue = @long;
|
||||
result = client.Write(varInfo.Address, @long);
|
||||
break;
|
||||
case DataTypeEnum.UInt64:
|
||||
var @ulong = ulong.Parse(value.ToString());
|
||||
convertValue = @ulong;
|
||||
result = client.Write(varInfo.Address, @ulong);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException($"变量为指定数据类型,或是非预期的数据类型{varInfo}");
|
||||
}
|
||||
|
||||
if (result.IsSucceed)
|
||||
{
|
||||
return convertValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(result.Err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 类型转换
|
||||
/// </summary>
|
||||
/// <param name="dataType"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
//public static Type ToDataType(this DataTypeEnum dataType)
|
||||
//{
|
||||
// Type plcDataType;
|
||||
// switch (dataType)
|
||||
// {
|
||||
// case DataTypeEnum.String:
|
||||
// plcDataType = typeof(string);
|
||||
// break;
|
||||
// case DataTypeEnum.Bool:
|
||||
// plcDataType = typeof(bool);
|
||||
// break;
|
||||
// case DataTypeEnum.Float:
|
||||
// plcDataType = typeof(float);
|
||||
// break;
|
||||
// case DataTypeEnum.Double:
|
||||
// plcDataType = typeof(double);
|
||||
// break;
|
||||
// case DataTypeEnum.Byte:
|
||||
// plcDataType = typeof(byte);
|
||||
// break;
|
||||
// case DataTypeEnum.Int16:
|
||||
// plcDataType = typeof(short);
|
||||
// break;
|
||||
// case DataTypeEnum.UInt16:
|
||||
// plcDataType = typeof(ushort);
|
||||
// break;
|
||||
// case DataTypeEnum.Int32:
|
||||
// plcDataType = typeof(int);
|
||||
// break;
|
||||
// case DataTypeEnum.UInt32:
|
||||
// plcDataType = typeof(uint);
|
||||
// break;
|
||||
// case DataTypeEnum.Int64:
|
||||
// plcDataType = typeof(long);
|
||||
// break;
|
||||
// case DataTypeEnum.UInt64:
|
||||
// plcDataType = typeof(ulong);
|
||||
// break;
|
||||
// default:
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// return plcDataType;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
using Net462DllTest.Signal;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Threading;
|
||||
using Serein.Library.Utils;
|
||||
|
||||
namespace Net462DllTest.Trigger
|
||||
{
|
||||
/// <summary>
|
||||
/// 视图管理
|
||||
/// </summary>
|
||||
[AutoRegister]
|
||||
public class ViewManagement : TaskFlowTrigger<CommandSignal>
|
||||
{
|
||||
private readonly UIContextOperation uiContextOperation;
|
||||
public ViewManagement(UIContextOperation uiContextOperation)
|
||||
{
|
||||
this.uiContextOperation = uiContextOperation;
|
||||
}
|
||||
public int Id = new Random().Next(1, 10000);
|
||||
private readonly List<Form> forms = new List<Form>();
|
||||
/// <summary>
|
||||
/// 打开窗口
|
||||
/// </summary>
|
||||
/// <param name="form">要打开的窗口类型</param>
|
||||
/// <param name="isTop">是否置顶</param>
|
||||
public void OpenView(Form form, bool isTop)
|
||||
{
|
||||
//Application.Current.Dispatcher.
|
||||
forms.Add(form);
|
||||
|
||||
uiContextOperation.Invoke(() => {
|
||||
form.TopMost = isTop;
|
||||
form.Show();
|
||||
});
|
||||
|
||||
|
||||
|
||||
//environment.IOC.Run<SynchronizationContext>(uiContext =>
|
||||
//{
|
||||
// uiContext?.Post(state => {
|
||||
|
||||
// },null);
|
||||
//});
|
||||
|
||||
//var uiContext = SynchronizationContext.Current;
|
||||
//Task.Run(() =>
|
||||
//{
|
||||
// uiContext.Post(_ =>
|
||||
// {
|
||||
|
||||
// }, null);
|
||||
//});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void CloseView(Type formType)
|
||||
{
|
||||
var remoteForms = forms.Where(f => f.GetType() == formType).ToArray();
|
||||
|
||||
Dispatcher.CurrentDispatcher.Invoke(() =>
|
||||
{
|
||||
foreach (Form f in remoteForms)
|
||||
{
|
||||
f.Close();
|
||||
f.Dispose();
|
||||
this.forms.Remove(f);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
using Serein.Library;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace Net462DllTest.Utils
|
||||
{
|
||||
public interface IGSModel<TKey, TModel>
|
||||
{
|
||||
//TModel Value { get; set; }
|
||||
void Set(TKey tEnum, object value);
|
||||
object Get(TKey tEnum);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通过 Emit 创建 set/get 委托
|
||||
/// </summary>
|
||||
public class GSModel<TKey, TModel> : IGSModel<TKey, TModel>
|
||||
where TKey : struct, Enum
|
||||
where TModel : class
|
||||
{
|
||||
private TModel Value;
|
||||
|
||||
public GSModel(TModel Model)
|
||||
{
|
||||
this.Value = Model;
|
||||
}
|
||||
// 缓存创建好的setter和getter委托
|
||||
private readonly Dictionary<TKey, Action<TModel, object>> _setterCache = new Dictionary<TKey, Action<TModel, object>>();
|
||||
private readonly Dictionary<TKey, Func<TModel, object>> _getterCache = new Dictionary<TKey, Func<TModel, object>>();
|
||||
|
||||
public void Set(TKey tEnum, object value)
|
||||
{
|
||||
if (!_setterCache.TryGetValue(tEnum, out var setter))
|
||||
{
|
||||
PropertyInfo property = GetPropertyByEnum(tEnum);
|
||||
if (property == null)
|
||||
{
|
||||
_setterCache[tEnum] = (s, o) => throw new ArgumentException($"没有对应的Model属性{{{tEnum}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 创建并缓存setter委托
|
||||
setter = CreateSetter(property);
|
||||
_setterCache[tEnum] = setter;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用缓存的setter委托设置值
|
||||
setter(Value, value);
|
||||
}
|
||||
|
||||
public object Get(TKey tEnum)
|
||||
{
|
||||
if (!_getterCache.TryGetValue(tEnum, out var getter))
|
||||
{
|
||||
PropertyInfo property = GetPropertyByEnum(tEnum);
|
||||
if (property == null)
|
||||
{
|
||||
_setterCache[tEnum] = (s, o) => throw new ArgumentException($"没有对应的Model属性{tEnum}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 创建并缓存getter委托
|
||||
getter = CreateGetter(property);
|
||||
_getterCache[tEnum] = getter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 使用缓存的getter委托获取值
|
||||
return getter(Value);
|
||||
}
|
||||
|
||||
private PropertyInfo GetPropertyByEnum(TKey tEnum)
|
||||
{
|
||||
foreach (var property in typeof(TModel).GetProperties())
|
||||
{
|
||||
var attribute = property.GetCustomAttribute<BindValueAttribute>();
|
||||
if (attribute?.Value?.GetType()?.IsEnum == true)
|
||||
{
|
||||
if (attribute.Value is TKey @enum && @enum.Equals(tEnum))
|
||||
{
|
||||
return property;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 动态创建调用Setter方法
|
||||
private Action<TModel, object> CreateSetter(PropertyInfo property)
|
||||
{
|
||||
var method = new DynamicMethod("Set" + property.Name, null, new[] { typeof(TModel), typeof(object) }, true);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0); // 加载实例(PlcVarValue)
|
||||
il.Emit(OpCodes.Ldarg_1); // 加载值(object)
|
||||
|
||||
if (property.PropertyType.IsValueType)
|
||||
{
|
||||
il.Emit(OpCodes.Unbox_Any, property.PropertyType); // 解箱并转换为值类型
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Castclass, property.PropertyType); // 引用类型转换
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Callvirt, property.GetSetMethod()); // 调用属性的Setter方法
|
||||
il.Emit(OpCodes.Ret); // 返回
|
||||
|
||||
|
||||
|
||||
return (Action<TModel, object>)method.CreateDelegate(typeof(Action<TModel, object>));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动态创建调用Getter方法
|
||||
/// </summary>
|
||||
/// <param name="property"></param>
|
||||
/// <returns></returns>
|
||||
private Func<TModel, object> CreateGetter(PropertyInfo property)
|
||||
{
|
||||
var method = new DynamicMethod("Get" + property.Name, typeof(object), new[] { typeof(TModel) }, true);
|
||||
var il = method.GetILGenerator();
|
||||
|
||||
il.Emit(OpCodes.Ldarg_0); // 加载实例(PlcVarValue)
|
||||
il.Emit(OpCodes.Callvirt, property.GetGetMethod()); // 调用属性的Getter方法
|
||||
|
||||
if (property.PropertyType.IsValueType)
|
||||
{
|
||||
il.Emit(OpCodes.Box, property.PropertyType); // 值类型需要装箱
|
||||
}
|
||||
|
||||
il.Emit(OpCodes.Ret); // 返回
|
||||
|
||||
return (Func<TModel, object>)method.CreateDelegate(typeof(Func<TModel, object>));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Net462DllTest.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于窗体View与ViewModel进行交互
|
||||
/// </summary>
|
||||
public class RelayCommand : ICommand
|
||||
{
|
||||
private readonly Action<object> _execute;
|
||||
private readonly Func<object,bool> _canExecute;
|
||||
|
||||
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
public bool CanExecute(object parameter = null)
|
||||
{
|
||||
return _canExecute == null || _canExecute(parameter);
|
||||
}
|
||||
|
||||
public void Execute(object parameter = null)
|
||||
{
|
||||
_execute(parameter);
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
|
||||
using Net462DllTest.Enums;
|
||||
using Net462DllTest.Signal;
|
||||
using Net462DllTest.Trigger;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Utils;
|
||||
using Serein.Library.Web;
|
||||
using System;
|
||||
|
||||
namespace Net462DllTest.Web
|
||||
{
|
||||
[WebApiController]
|
||||
public class FlowController : ControllerBase
|
||||
{
|
||||
private readonly SiemensPlcDevice plcDevice;
|
||||
private readonly ViewManagement viewManagement;
|
||||
|
||||
public FlowController(SiemensPlcDevice plcDevice, ViewManagement viewManagement)
|
||||
{
|
||||
this.plcDevice = plcDevice;
|
||||
this.viewManagement = viewManagement;
|
||||
}
|
||||
|
||||
/*
|
||||
* 类型 :POST
|
||||
* url : http://127.0.0.1:8089/flow/plcop?var=
|
||||
* url : http://127.0.0.1:8089/flow/plcop?var=SpaceNum
|
||||
* body :[JSON]
|
||||
*
|
||||
* {
|
||||
* "value":0,
|
||||
* }
|
||||
*/
|
||||
[WebApi(ApiType.POST)]
|
||||
public dynamic PlcOp([Url] string var, int value)
|
||||
{
|
||||
if (EnumHelper.TryConvertEnum<PlcVarName>(var, out var signal))
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"外部触发 {signal} 信号,信号内容 : {value} ");
|
||||
_ = plcDevice.InvokeTriggerAsync(signal, value);// 通过 Web Api 模拟外部输入信号
|
||||
return new { state = "succeed" };
|
||||
}
|
||||
else
|
||||
{
|
||||
return new { state = "fail" };
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 类型 :POST
|
||||
* url : http://127.0.0.1:8089/flow/trigger?command=
|
||||
* url : http://127.0.0.1:8089/flow/trigger?command=Command_1
|
||||
* body :[JSON]
|
||||
*
|
||||
* {
|
||||
* "value":0,
|
||||
* }
|
||||
*/
|
||||
[WebApi(ApiType.POST)]
|
||||
public dynamic Trigger([Url] string command, int value)
|
||||
{
|
||||
if (EnumHelper.TryConvertEnum<CommandSignal>(command, out var signal))
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"外部触发 {signal} 信号,信号内容 : {value} ");
|
||||
_ = viewManagement.InvokeTriggerAsync(signal, value);// 通过 Web Api 模拟外部输入信号
|
||||
return new { state = "succeed" };
|
||||
}
|
||||
else
|
||||
{
|
||||
return new { state = "fail" };
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
using IoTClient.Common.Enums;
|
||||
using Net462DllTest.Enums;
|
||||
using Net462DllTest.Model;
|
||||
using Net462DllTest.Trigger;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Network.WebSocketCommunication;
|
||||
using Serein.Library.Web;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Net462DllTest.Web
|
||||
{
|
||||
|
||||
[AutoRegister]
|
||||
[DynamicFlow("[PlcSocketService]")]
|
||||
[AutoSocketModule(ThemeKey = "theme", DataKey = "data")]
|
||||
public class PlcSocketService : ISocketHandleModule
|
||||
{
|
||||
public Guid HandleGuid { get; } = new Guid();
|
||||
|
||||
private readonly SiemensPlcDevice MyPlc;
|
||||
private readonly PlcVarModelDataProxy plcVarModelDataProxy;
|
||||
|
||||
public PlcSocketService(SiemensPlcDevice MyPlc,
|
||||
PlcVarModelDataProxy plcVarModelDataProxy)
|
||||
{
|
||||
this.MyPlc = MyPlc;
|
||||
this.plcVarModelDataProxy = plcVarModelDataProxy;
|
||||
}
|
||||
|
||||
#region 初始化、初始化完成以及退出的事件
|
||||
[NodeAction(NodeType.Init)]
|
||||
public void Init(IFlowContext context)
|
||||
{
|
||||
var ioc = context.Env.FlowControl.IOC;
|
||||
ioc.Register<WebSocketServer>();
|
||||
ioc.Register<WebSocketClient>();
|
||||
|
||||
ioc.Register<IRouter, Router>();
|
||||
ioc.Register<WebApiServer>();
|
||||
}
|
||||
|
||||
[NodeAction(NodeType.Loading)] // Loading 初始化完成已注入依赖项,可以开始逻辑上的操作
|
||||
public void Loading(IFlowContext context)
|
||||
{
|
||||
var ioc = context.Env.FlowControl.IOC;
|
||||
// 注册控制器
|
||||
ioc.Run<IRouter, WebApiServer>((router, apiServer) => {
|
||||
router.AddHandle(typeof(FlowController));
|
||||
apiServer.Start("http://*:8089/"); // 开启 Web Api 服务
|
||||
});
|
||||
|
||||
ioc.Run<WebSocketServer>(async (socketServer) => {
|
||||
socketServer.MsgHandleHelper.AddModule(this, (ex, recover) =>
|
||||
{
|
||||
recover(new
|
||||
{
|
||||
ex = ex.Message,
|
||||
storehouseInfo = ex.StackTrace
|
||||
});
|
||||
|
||||
});
|
||||
await socketServer.StartAsync("http://localhost:5005/"); // 开启 Web Socket 监听
|
||||
});
|
||||
ioc.Run<WebSocketClient>(async client => {
|
||||
await client.ConnectAsync("ws://localhost:5005/"); // 连接到服务器
|
||||
});
|
||||
}
|
||||
|
||||
[NodeAction(NodeType.Exit)] // 流程结束时自动执行
|
||||
public void Exit(IFlowContext context)
|
||||
{
|
||||
var ioc = context.Env.FlowControl.IOC;
|
||||
ioc.Run<WebApiServer>((apiServer) =>
|
||||
{
|
||||
apiServer?.Stop(); // 关闭 Web 服务
|
||||
|
||||
});
|
||||
ioc.Run<WebSocketServer>((socketServer) =>
|
||||
{
|
||||
socketServer.MsgHandleHelper.RemoveModule(this);
|
||||
socketServer?.Stop(); // 关闭 Web 服务
|
||||
});
|
||||
MyPlc.Close();
|
||||
MyPlc.CancelAllTrigger();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
[AutoSocketHandle]
|
||||
public async Task BatchReadVar(Func<string, Task> SendMsg, Func<object, Task> SendObj)
|
||||
{
|
||||
await SendMsg("开始刷新数据");
|
||||
//MyPlc.BatchRefresh();
|
||||
await Task.Delay(1000);
|
||||
await SendMsg("刷新完成");
|
||||
await SendObj(plcVarModelDataProxy);
|
||||
await SendMsg("发送完成");
|
||||
}
|
||||
|
||||
|
||||
[AutoSocketHandle]
|
||||
public object ReadVar(PlcVarName varName)
|
||||
{
|
||||
var result = MyPlc.Read(varName);
|
||||
Console.WriteLine($"获取变量成功:({varName})\t result = {result}");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[AutoSocketHandle(IsReturnValue = false)]
|
||||
public SiemensPlcDevice WriteVar(object value, PlcVarName varName)
|
||||
{
|
||||
MyPlc.Write(varName, value); // 新数据
|
||||
return MyPlc;
|
||||
}
|
||||
[AutoSocketHandle(IsReturnValue = false)]
|
||||
public SiemensPlcDevice PlcInit(SiemensVersion version = SiemensVersion.None,
|
||||
string ip = "192.168.10.100",
|
||||
int port = 102)
|
||||
{
|
||||
if (MyPlc.Client is null)
|
||||
{
|
||||
try
|
||||
{
|
||||
MyPlc.Init(version, ip, port);
|
||||
Console.WriteLine($"西门子PLC初始化成功[{version},{ip}:{port}]");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"西门子PLC[{version},{ip}:{port}]初始化异常:{ex.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"西门子PLC已经初始化[{version},{ip}:{port}]");
|
||||
}
|
||||
return MyPlc;
|
||||
}
|
||||
|
||||
[AutoSocketHandle(IsReturnValue = false)]
|
||||
public SiemensPlcDevice SetState(PlcState state = PlcState.PowerOff)
|
||||
{
|
||||
var oldState = MyPlc.State;
|
||||
MyPlc.State = state;
|
||||
Console.WriteLine($"PLC状态从[{oldState}]转为[{state}]");
|
||||
return MyPlc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void OpenTimedRefresh()
|
||||
{
|
||||
Task.Run(async () => await MyPlc.OpenTimedRefreshAsync());
|
||||
}
|
||||
|
||||
public void CloseTimedRefresh()
|
||||
{
|
||||
MyPlc.CloseTimedRefresh();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.IO.Ports" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup></configuration>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="IoTClient" version="1.0.40" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" />
|
||||
<package id="System.IO.Ports" version="4.6.0" targetFramework="net461" />
|
||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user