1473 lines
50 KiB
C#
1473 lines
50 KiB
C#
using HslCommunication;
|
||||
|
|
using HslCommunication.Profinet.Omron;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Net;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Text.RegularExpressions;
|
|||
|
|
using System.Threading;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using System.Windows.Forms;
|
|||
|
|
|
|||
|
|
namespace PLCCommunication
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
// 摘要:
|
|||
|
|
// 欧姆龙PLC通讯类,采用Fins-Tcp通信协议实现,支持的地址信息参见api文档信息。
|
|||
|
|
// Omron PLC communication class is implemented using Fins-Tcp communication protocol.
|
|||
|
|
// For the supported address information, please refer to the api document information.
|
|||
|
|
//
|
|||
|
|
// 言论:
|
|||
|
|
// 实例化之后,使用之前,需要初始化三个参数信息,具体见三个参数的说明:HslCommunication.Profinet.Omron.OmronFinsNet.SA1,HslCommunication.Profinet.Omron.OmronFinsNet.DA1,HslCommunication.Profinet.Omron.OmronFinsNet.DA2
|
|||
|
|
// 第二个需要注意的是,当网络异常掉线时,无法立即连接上PLC,PLC对于当前的节点进行拒绝,如果想要支持在断线后的快速连接,就需要将 HslCommunication.Profinet.Omron.OmronFinsNet.IsChangeSA1AfterReadFailed设置为True,详细的可以参考
|
|||
|
|
// HslCommunication.Profinet.Omron.OmronFinsNet.IsChangeSA1AfterReadFailed
|
|||
|
|
// 如果在测试的时候报错误码64,经网友 上海-Lex 指点,是因为PLC中产生了报警,如伺服报警,模块错误等产生的,但是数据还是能正常读到的,屏蔽64报警或清除plc错误可解决
|
|||
|
|
// 地址支持的列表如下:
|
|||
|
|
// 地址名称 – 地址代号 – 示例 – 地址进制 – 字操作 – 位操作 – 备注 –
|
|||
|
|
// DM Area – D – D100,D200 – 10 – √ – √ – –
|
|||
|
|
// CIO Area – C – C100,C200 – 10 – √ – √ – –
|
|||
|
|
// Work Area – W – W100,W200 – 10 – √ – √ – –
|
|||
|
|
// Holding Bit Area – H – H100,H200 – 10 – √ – √ – –
|
|||
|
|
// Auxiliary Bit Area – A – A100,A200 – 10 – √ – √ – –
|
|||
|
|
// EM Area – E – E0.0,EF.200,E10.100 – 10 – √ – √ – –
|
|||
|
|
|
|||
|
|
public partial class OmronPLCUI : UserControl
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 批量读取PLC数据委托
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="Index"></param>
|
|||
|
|
/// <param name="msg"></param>
|
|||
|
|
/// <param name="resByte"></param>
|
|||
|
|
public delegate void ReceiveHandler(int Index, string msg, OperateResult<byte[]> resByte);
|
|||
|
|
public event ReceiveHandler ReceiveEvent;
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取PLC心跳消息状态至主窗口委托
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="b"></param>
|
|||
|
|
public delegate void UpHeartBeatHandler(bool b);
|
|||
|
|
public event UpHeartBeatHandler UpHeartBeatEvent;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 保存配置事件委托
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="plcIndex"></param>
|
|||
|
|
/// <param name="trgIndex"></param>
|
|||
|
|
public delegate void SaveParamsHandler(int plcIndex, int trgIndex);
|
|||
|
|
public event SaveParamsHandler SaveParamsEvent;
|
|||
|
|
|
|||
|
|
public int Index;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 欧姆龙Fins协议
|
|||
|
|
/// </summary>
|
|||
|
|
public HslCommunication.Profinet.Omron.OmronCipNet omronCipNet = null;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 是否链接PLC
|
|||
|
|
/// </summary>
|
|||
|
|
private bool _isConnected = false;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 是否开启心跳消息
|
|||
|
|
/// </summary>
|
|||
|
|
private bool _heartBeat = false;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 断线后是否更换SA1的值
|
|||
|
|
/// </summary>
|
|||
|
|
private bool _changesa1 = false;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 心跳消息寄存器地址
|
|||
|
|
/// </summary>
|
|||
|
|
private string _heartAddr = "100";
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
public Dictionary<string, TriggerParams> dicJobToTrgParams = new Dictionary<string, TriggerParams>();
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
public List<TriggerUI> lstTrgUI = new List<TriggerUI>();
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
public List<TriggerParams> lstTgrParams = new List<TriggerParams>();
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
public PLCConfig PlcConfig = new PLCConfig();
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
public CancellationTokenSource mCTSRecv = new CancellationTokenSource();
|
|||
|
|
public CancellationTokenSource mCTSHeart = new CancellationTokenSource();
|
|||
|
|
private ManualResetEvent resetEventRecv = new ManualResetEvent(true);
|
|||
|
|
private ManualResetEvent resetEventHeart = new ManualResetEvent(true);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
public bool IsConnected
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _isConnected;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_isConnected = value;
|
|||
|
|
if (_isConnected)
|
|||
|
|
{
|
|||
|
|
//lblConnectStatus.ForeColor = Color.Green;
|
|||
|
|
lblConnectStatus.Image = Properties.Resources.green;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
lblConnectStatus.Image = Properties.Resources.red;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
public bool IsRun { get; set; } = false;
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
private string CurrentTime => DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:fff");
|
|||
|
|
|
|||
|
|
public bool HeartBeat
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _heartBeat;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_heartBeat = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public bool ChangeSA1
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _changesa1;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_changesa1 = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
public string HeartAddr
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _heartAddr;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
_heartAddr = value;
|
|||
|
|
txtHeartAddr.Text = value.ToString();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取PLC数据线程等待时间
|
|||
|
|
/// </summary>
|
|||
|
|
public int ScanTime { get; set; } = 100;
|
|||
|
|
public int JobCount { get; set; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// PLCIP地址
|
|||
|
|
/// </summary>
|
|||
|
|
public string IP { get; set; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// PLC端口
|
|||
|
|
/// </summary>
|
|||
|
|
public int Port { get; set; }
|
|||
|
|
public bool DispCurrent { get; set; } = false;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
public OmronPLCUI()
|
|||
|
|
{
|
|||
|
|
InitializeComponent();
|
|||
|
|
omronCipNet = new OmronCipNet();
|
|||
|
|
omronCipNet.ConnectTimeOut = 2000;
|
|||
|
|
PanelTest.Enabled = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public OmronPLCUI(PLCConfig plcConfig)
|
|||
|
|
: this()
|
|||
|
|
{
|
|||
|
|
PlcConfig = plcConfig;
|
|||
|
|
Index = plcConfig.Index;
|
|||
|
|
IP = plcConfig.IP;
|
|||
|
|
Port = plcConfig.Port;
|
|||
|
|
JobCount = plcConfig.JobCount;
|
|||
|
|
ScanTime = plcConfig.ScanTime;
|
|||
|
|
HeartBeat = plcConfig.HeartBeat;
|
|||
|
|
ChangeSA1 = plcConfig.ChangeSA1;
|
|||
|
|
lstTgrParams = plcConfig.lstTgrParams;
|
|||
|
|
_heartAddr = plcConfig.HeartAddr;
|
|||
|
|
|
|||
|
|
InitialTiggerModule(lstTgrParams);
|
|||
|
|
cboReadType.DataSource = Enum.GetNames(typeof(VarType));
|
|||
|
|
cboReadType.SelectedIndex = 0;
|
|||
|
|
if (HeartBeat)
|
|||
|
|
{
|
|||
|
|
cbHeartBeat.Checked = true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
cbHeartBeat.Checked = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
txtIP.Text = PlcConfig.IP.Trim();
|
|||
|
|
txtPort.Text = PlcConfig.Port.ToString();
|
|||
|
|
txtHeartAddr.Text = PlcConfig.HeartAddr;
|
|||
|
|
txtSolt.Text = PlcConfig.Solt.ToString();
|
|||
|
|
InitialAndConnect();
|
|||
|
|
Task HeartTask = Task.Factory.StartNew(delegate { CheckHeart(); }, mCTSHeart.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
|||
|
|
if (!IsRun)
|
|||
|
|
{
|
|||
|
|
resetEventRecv.Reset();
|
|||
|
|
}
|
|||
|
|
SetStyle(ControlStyles.UserPaint, true);
|
|||
|
|
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
|||
|
|
SetStyle(ControlStyles.DoubleBuffer, true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
private void MelsecPLCUI_Load(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
List<string> ipv4_ips = GetLocalIpAddress("InterNetwork");//获取ipv4类型的ip
|
|||
|
|
//string da = ipv4_ips[0].LastIndexOf('.')-1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//List<string> ips = GetLocalIpAddress("");//获取本地所有ip
|
|||
|
|
//List<string> ipv4_ips = GetLocalIpAddress("InterNetwork");//获取ipv4类型的ip
|
|||
|
|
//List<string> ipv6_ips = GetLocalIpAddress("InterNetworkV6");//获取ipv6类型的ip
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取本机所有ip地址
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="netType">"InterNetwork":ipv4地址,"InterNetworkV6":ipv6地址</param>
|
|||
|
|
/// <returns>ip地址集合</returns>
|
|||
|
|
public static List<string> GetLocalIpAddress(string netType)
|
|||
|
|
{
|
|||
|
|
string hostName = Dns.GetHostName(); //获取主机名称
|
|||
|
|
IPAddress[] addresses = Dns.GetHostAddresses(hostName); //解析主机IP地址
|
|||
|
|
|
|||
|
|
List<string> IPList = new List<string>();
|
|||
|
|
if (netType == string.Empty)
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < addresses.Length; i++)
|
|||
|
|
{
|
|||
|
|
IPList.Add(addresses[i].ToString());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//AddressFamily.InterNetwork表示此IP为IPv4,
|
|||
|
|
//AddressFamily.InterNetworkV6表示此地址为IPv6类型
|
|||
|
|
for (int i = 0; i < addresses.Length; i++)
|
|||
|
|
{
|
|||
|
|
if (addresses[i].AddressFamily.ToString() == netType)
|
|||
|
|
{
|
|||
|
|
if (addresses[i].ToString().Contains("192"))
|
|||
|
|
{
|
|||
|
|
IPList.Add(addresses[i].ToString());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return IPList;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void InitialTiggerModule(List<TriggerParams> lstTrgParams)
|
|||
|
|
{
|
|||
|
|
tabConTrgUI.TabPages.Clear();
|
|||
|
|
for (int i = 0; i < lstTrgParams.Count; i++)
|
|||
|
|
{
|
|||
|
|
TriggerUI triggerUI = new TriggerUI(lstTrgParams[i]);
|
|||
|
|
tabConTrgUI.TabPages.Add(lstTrgParams[i].ThreadName);
|
|||
|
|
Panel panel = new Panel();
|
|||
|
|
tabConTrgUI.TabPages[i].Controls.Add(panel);
|
|||
|
|
panel.Dock = DockStyle.Fill;
|
|||
|
|
panel.Controls.Add(triggerUI);
|
|||
|
|
triggerUI.Dock = DockStyle.Fill;
|
|||
|
|
triggerUI.TrgParamChangeEvent += TriggerUI_TrgParamChangeEvent;
|
|||
|
|
lstTrgUI.Add(triggerUI);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void TriggerUI_TrgParamChangeEvent(int tgrIndex)
|
|||
|
|
{
|
|||
|
|
OnSaveParams(Index, tgrIndex);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public bool Connect()
|
|||
|
|
{
|
|||
|
|
if (!IPAddress.TryParse(txtIP.Text, out IPAddress address))
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "PLCIP地址格式不正确");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
if (!int.TryParse(txtPort.Text, out int port))
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "端口号格式不正确");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
if (!byte.TryParse(txtSolt.Text, out byte solt))
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "PLC插槽号设置错误!");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
string str = "";
|
|||
|
|
omronCipNet.IpAddress = address.ToString();
|
|||
|
|
omronCipNet.Port = port;
|
|||
|
|
omronCipNet.Slot = solt;
|
|||
|
|
omronCipNet.ConnectClose();
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
omronCipNet.ConnectTimeOut = 2000;
|
|||
|
|
OperateResult connect = omronCipNet.ConnectServer();
|
|||
|
|
if (connect.IsSuccess)
|
|||
|
|
{
|
|||
|
|
IsConnected = true;
|
|||
|
|
BtnDisConnect.Enabled = true;
|
|||
|
|
BtnConnect.Enabled = false;
|
|||
|
|
str = StringResources.Language.ConnectedSuccess;
|
|||
|
|
AddLog(lstRecv, 0, StringResources.Language.ConnectedSuccess);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
IsConnected = false;
|
|||
|
|
str = StringResources.Language.ConnectedFailed;
|
|||
|
|
AddLog(lstRecv,1, StringResources.Language.ConnectedFailed);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
str = ex.Message;
|
|||
|
|
IsConnected = false;
|
|||
|
|
AddLog(lstRecv, 1, ex.Message);
|
|||
|
|
}
|
|||
|
|
//LogManagerControl.AddLog($"{str}", LogAddtype.local, Logtype.Message);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 对PLC进行链接
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void BtnConnect_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
Connect();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 与LC断开链接
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void BtnDisConnect_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
ConnectClose();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 断开PLC的链接
|
|||
|
|
/// </summary>
|
|||
|
|
public void ConnectClose()
|
|||
|
|
{
|
|||
|
|
omronCipNet.ConnectClose();
|
|||
|
|
BtnDisConnect.Enabled = false;
|
|||
|
|
BtnConnect.Enabled = true;
|
|||
|
|
lblConnectStatus.Image = Properties.Resources.red;
|
|||
|
|
IsConnected = false;
|
|||
|
|
AddLog(lstRecv, 0, "断开连接");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 界面测试复选框
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void cbTest_CheckedChanged(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
if (cbTest.Checked)
|
|||
|
|
{
|
|||
|
|
PanelTest.Enabled = true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
PanelTest.Enabled = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取PLC数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void BtnReadTest_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
if (!IsConnected)
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "未连接到PLC,请检查连接状态");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (txtReadAddrTest.Text.Trim() == "")
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "读取地址不能为空");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (txtReadTestLength.Text.Trim() == "")
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "读取长度不能为空");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
switch ((VarType)Enum.Parse(typeof(VarType), cboReadType.SelectedItem.ToString(), false))
|
|||
|
|
{
|
|||
|
|
case VarType.Bit:
|
|||
|
|
DemoUtils.ReadResultRender(omronCipNet.ReadBool(txtReadAddrTest.Text, ushort.Parse(txtReadTestLength.Text.Trim())), txtReadAddrTest.Text, txtReadResultTest);
|
|||
|
|
break;
|
|||
|
|
case VarType.Short:
|
|||
|
|
DemoUtils.ReadResultRender(omronCipNet.ReadInt16(txtReadAddrTest.Text, ushort.Parse(txtReadTestLength.Text.Trim())), txtReadAddrTest.Text, txtReadResultTest);
|
|||
|
|
break;
|
|||
|
|
case VarType.Int:
|
|||
|
|
DemoUtils.ReadResultRender(omronCipNet.ReadInt32(txtReadAddrTest.Text, ushort.Parse(txtReadTestLength.Text.Trim())), txtReadAddrTest.Text, txtReadResultTest);
|
|||
|
|
break;
|
|||
|
|
case VarType.Float:
|
|||
|
|
DemoUtils.ReadResultRender(omronCipNet.ReadFloat(txtReadAddrTest.Text, ushort.Parse(txtReadTestLength.Text.Trim())), txtReadAddrTest.Text, txtReadResultTest);
|
|||
|
|
break;
|
|||
|
|
case VarType.String:
|
|||
|
|
DemoUtils.ReadResultRender(omronCipNet.ReadString(txtReadAddrTest.Text, ushort.Parse(txtReadTestLength.Text.Trim())), txtReadAddrTest.Text, txtReadResultTest);
|
|||
|
|
break;
|
|||
|
|
case VarType.Byte:
|
|||
|
|
DemoUtils.ReadResultRender(omronCipNet.Read(txtReadAddrTest.Text, ushort.Parse(txtReadTestLength.Text.Trim())), txtReadAddrTest.Text, txtReadResultTest);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "读取失败,请检查地址类型或连接状态" + ex.Message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入PLC数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void BtnWriteTest_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
if (!IsConnected)
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "未连接到PLC,请检查连接状态");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (txtReadAddrTest.Text.Trim() == "")
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "写入地址不能位空");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (txtReadTestLength.Text.Trim() == "")
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "写入长度不能为空");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
VarType varType = (VarType)Enum.Parse(typeof(VarType), cboReadType.SelectedItem.ToString(), false);
|
|||
|
|
switch (varType)
|
|||
|
|
{
|
|||
|
|
case VarType.Bit:
|
|||
|
|
{
|
|||
|
|
string type = txtWriteValue.Text.Trim().Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
MessageBox.Show("暂只支持D,W存储区");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
bool[] boolArray = GetBoolArray(txtWriteValue.Text.Trim());
|
|||
|
|
DemoUtils.WriteResultRender(() => omronCipNet.Write(txtReadAddrTest.Text.Trim(), boolArray), txtReadAddrTest.Text.Trim());
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case VarType.Short:
|
|||
|
|
{
|
|||
|
|
short[] shortArray = GetShortArray(txtWriteValue.Text.Trim());
|
|||
|
|
DemoUtils.WriteResultRender(() => omronCipNet.Write(txtReadAddrTest.Text.Trim(), shortArray), txtReadAddrTest.Text.Trim());
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case VarType.Int:
|
|||
|
|
{
|
|||
|
|
int[] intArray = GetIntArray(txtWriteValue.Text.Trim());
|
|||
|
|
DemoUtils.WriteResultRender(() => omronCipNet.Write(txtReadAddrTest.Text.Trim(), intArray), txtReadAddrTest.Text.Trim());
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case VarType.Float:
|
|||
|
|
{
|
|||
|
|
float[] floatArray = GetFloatArray(txtWriteValue.Text.Trim());
|
|||
|
|
DemoUtils.WriteResultRender(() => omronCipNet.Write(txtReadAddrTest.Text.Trim(), floatArray), txtReadAddrTest.Text.Trim());
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case VarType.Byte:
|
|||
|
|
{
|
|||
|
|
DemoUtils.WriteResultRender(() => omronCipNet.Write(txtReadAddrTest.Text.Trim(), txtWriteValue.Text.Trim()), txtReadAddrTest.Text.Trim());
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case VarType.String:
|
|||
|
|
{
|
|||
|
|
DemoUtils.WriteResultRender(() => omronCipNet.Write(txtReadAddrTest.Text.Trim(), txtWriteValue.Text.Trim()), txtReadAddrTest.Text.Trim());
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "写入失败,请检查地址类型或连接状态" + ex.Message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 开启
|
|||
|
|
/// </summary>
|
|||
|
|
public void InitialAndConnect()
|
|||
|
|
{
|
|||
|
|
Task RecvTask = Task.Factory.StartNew(delegate { GetMelsecValue(); }, mCTSRecv.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 链接PLC状态
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="status"></param>
|
|||
|
|
public void OmronStart(bool status)
|
|||
|
|
{
|
|||
|
|
if (status)
|
|||
|
|
{
|
|||
|
|
resetEventRecv.Set();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
resetEventRecv.Reset();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 循环读取PLC数据
|
|||
|
|
/// </summary>
|
|||
|
|
private void GetMelsecValue()
|
|||
|
|
{
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
if (mCTSRecv.Token.IsCancellationRequested)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
resetEventRecv.WaitOne();
|
|||
|
|
if (IsRun)
|
|||
|
|
{
|
|||
|
|
if (IsConnected)
|
|||
|
|
{
|
|||
|
|
OperateResult<byte[]> resByte = null;
|
|||
|
|
for (int i = 0; i < JobCount; i++)
|
|||
|
|
{
|
|||
|
|
StringBuilder res = new StringBuilder(string.Empty);
|
|||
|
|
switch (lstTrgUI[i].TrgParams.TriggerType)
|
|||
|
|
{
|
|||
|
|
case VarType.Bit:
|
|||
|
|
res.Append(omronCipNet.ReadBool(lstTrgUI[i].TrgParams.TriggerAddr).Content.ToString());
|
|||
|
|
break;
|
|||
|
|
case VarType.Short:
|
|||
|
|
res.Append(omronCipNet.ReadInt16(lstTrgUI[i].TrgParams.TriggerAddr).Content.ToString());
|
|||
|
|
break;
|
|||
|
|
case VarType.Int:
|
|||
|
|
res.Append(omronCipNet.ReadInt32(lstTrgUI[i].TrgParams.TriggerAddr).Content.ToString());
|
|||
|
|
break;
|
|||
|
|
case VarType.Float:
|
|||
|
|
res.Append(omronCipNet.ReadFloat(lstTrgUI[i].TrgParams.TriggerAddr).Content.ToString());
|
|||
|
|
break;
|
|||
|
|
case VarType.String:
|
|||
|
|
res.Append(omronCipNet.ReadString(lstTrgUI[i].TrgParams.TriggerAddr, Convert.ToUInt16(txtReadTestLength.Text.Trim())).Content.ToString());
|
|||
|
|
break;
|
|||
|
|
case VarType.Byte:
|
|||
|
|
resByte = omronCipNet.Read(lstTrgUI[i].TrgParams.TriggerAddr, Convert.ToUInt16(txtReadTestLength.Text.Trim()));
|
|||
|
|
res.Append(HslCommunication.BasicFramework.SoftBasic.ByteToHexString(resByte.Content));
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
if (lstTrgUI[i].TrgParams.IsRead)
|
|||
|
|
{
|
|||
|
|
resByte = omronCipNet.Read(lstTrgUI[i].TrgParams.ReadAddr, Convert.ToUInt16(lstTrgUI[i].TrgParams.ReadLength));
|
|||
|
|
//res.Append(HslCommunication.BasicFramework.SoftBasic.ByteToHexString(resByte.Content));
|
|||
|
|
}
|
|||
|
|
if (DispCurrent)
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 0, lstTrgUI[i].TrgParams.TriggerAddr + "-->" + res.ToString());
|
|||
|
|
}
|
|||
|
|
if (res.ToString() == lstTrgUI[i].TrgParams.TriggerCmd)
|
|||
|
|
{
|
|||
|
|
AddLog(lstTrgCmd, 0, $"{lstTrgUI[i].TrgParams.TriggerAddr}-->{res}");
|
|||
|
|
}
|
|||
|
|
OnReceive(i + 1, res.ToString(), resByte);
|
|||
|
|
Thread.Sleep(5);
|
|||
|
|
}
|
|||
|
|
Thread.Sleep(ScanTime);
|
|||
|
|
}
|
|||
|
|
else if (HeartBeat)
|
|||
|
|
{
|
|||
|
|
Thread.Sleep(5000);
|
|||
|
|
if (!IPAddress.TryParse(txtIP.Text, out IPAddress address))
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "PLCIP地址格式不正确");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (!int.TryParse(txtPort.Text, out int port))
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "端口号格式不正确");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (!byte.TryParse(txtSolt.Text, out byte solt))
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "PLC单元设置错误");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
omronCipNet.IpAddress = address.ToString();
|
|||
|
|
omronCipNet.Port = port;
|
|||
|
|
omronCipNet.Slot = solt;
|
|||
|
|
omronCipNet.ConnectTimeOut = 2000;
|
|||
|
|
OperateResult connect = omronCipNet.ConnectServer();
|
|||
|
|
if (connect.IsSuccess)
|
|||
|
|
{
|
|||
|
|
Invoke((Action)delegate
|
|||
|
|
{
|
|||
|
|
IsConnected = true;
|
|||
|
|
BtnDisConnect.Enabled = true;
|
|||
|
|
BtnConnect.Enabled = false;
|
|||
|
|
lblConnectStatus.Image = Properties.Resources.red;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Thread.Sleep(10000);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Thread.Sleep(2000);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
AddLog(lstRecv, 1, "端口号格式不正确");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 心跳消息
|
|||
|
|
/// </summary>
|
|||
|
|
private void CheckHeart()
|
|||
|
|
{
|
|||
|
|
while (!mCTSHeart.Token.IsCancellationRequested)
|
|||
|
|
{
|
|||
|
|
if (IsRun)
|
|||
|
|
{
|
|||
|
|
if (HeartBeat)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
Thread.Sleep(1000);
|
|||
|
|
OperateResult result = omronCipNet.Write(HeartAddr, (short)1);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
OnUpHeartBeat(true);
|
|||
|
|
AddLog(lstSend, 0, $"心跳 {txtHeartAddr.Text}-> {1}");
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
Invoke((Action)delegate
|
|||
|
|
{
|
|||
|
|
OnUpHeartBeat(false);
|
|||
|
|
IsConnected = false;
|
|||
|
|
BtnConnect.Enabled = true;
|
|||
|
|
BtnDisConnect.Enabled = false;
|
|||
|
|
//lblConnectStatus.IsFlash = false;
|
|||
|
|
//lblConnectStatus.LedStatus = false;
|
|||
|
|
|
|||
|
|
});
|
|||
|
|
AddLog(lstSend, 2, $"心跳 {txtHeartAddr.Text}-> {1}失败");
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Invoke((Action)delegate
|
|||
|
|
{
|
|||
|
|
OnUpHeartBeat(false);
|
|||
|
|
IsConnected = false;
|
|||
|
|
BtnConnect.Enabled = true;
|
|||
|
|
BtnDisConnect.Enabled = false;
|
|||
|
|
//lblConnectStatus.IsFlash = false;
|
|||
|
|
//lblConnectStatus.LedStatus = false;
|
|||
|
|
|
|||
|
|
});
|
|||
|
|
AddLog(lstSend, 2, ex.Message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Thread.Sleep(1000);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 对PLC某寄存器清零
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <param name="varType"></param>
|
|||
|
|
public void ClearReg(string iAddr, VarType varType)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
switch (varType)
|
|||
|
|
{
|
|||
|
|
case VarType.Bit:
|
|||
|
|
omronCipNet.Write(iAddr, false);
|
|||
|
|
break;
|
|||
|
|
case VarType.Float:
|
|||
|
|
omronCipNet.Write(iAddr, 0f);
|
|||
|
|
break;
|
|||
|
|
case VarType.Short:
|
|||
|
|
omronCipNet.Write(iAddr, (short)0);
|
|||
|
|
break;
|
|||
|
|
case VarType.Int:
|
|||
|
|
omronCipNet.Write(iAddr, 0);
|
|||
|
|
break;
|
|||
|
|
case VarType.String:
|
|||
|
|
omronCipNet.Write(iAddr, 0);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
///读取BOOL值
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public bool ReadBoolDReg(string iAddr)
|
|||
|
|
{
|
|||
|
|
bool result = false;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
result = omronCipNet.ReadBool(iAddr).Content;
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {result.ToString()}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {ex.Message}");
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
///读取String值
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public string ReadStringDReg(string iAddr)
|
|||
|
|
{
|
|||
|
|
string result = "";
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
result = omronCipNet.ReadString(iAddr).Content;
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {result}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {ex.Message}");
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取16位整数
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public short ReadshortDReg(string iAddr)
|
|||
|
|
{
|
|||
|
|
short result = 0;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
result = omronCipNet.ReadInt16(iAddr).Content;
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {result.ToString()}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {ex.Message}");
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取32位整数
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public int ReadIntDReg(string iAddr)
|
|||
|
|
{
|
|||
|
|
int result = 0;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W" && type != "H")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
result = omronCipNet.ReadInt32(iAddr).Content;
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {result.ToString()}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {ex.Message}");
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取浮点数
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public float ReadFloatDReg(string iAddr)
|
|||
|
|
{
|
|||
|
|
float result = 0;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W" && type != "H")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
result = omronCipNet.ReadFloat(iAddr).Content;
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {result.ToString()}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {ex.Message}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 读取byte
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr">数据地址</param>
|
|||
|
|
/// <param name="lenght">读取长度</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public byte[] Readbyte(string iAddr, ushort lenght)
|
|||
|
|
{
|
|||
|
|
byte[] result = null;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
//string type = iAddr.Substring(0, 1);
|
|||
|
|
//if (type != "D" && type != "R")
|
|||
|
|
//{
|
|||
|
|
// AddLog(lstSend, 2, "暂只支持D,R存储区");
|
|||
|
|
//}
|
|||
|
|
if (IsConnected)
|
|||
|
|
{
|
|||
|
|
result = omronCipNet.Read(iAddr, lenght).Content;
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {result.ToString()}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {ex.Message}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入byte数组
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <param name="Value"></param>
|
|||
|
|
public void WriteDReg(string iAddr, byte[] Value)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
OperateResult result = omronCipNet.Write(iAddr, Value);
|
|||
|
|
//OperateResult result = omronCipNet.WriteTag(iAddr,210, Value);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
public void WriteDReg(string iAddr, float Value)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
OperateResult result = omronCipNet.Write(iAddr, Value);
|
|||
|
|
//OperateResult result = omronCipNet.WriteTag(iAddr,210, Value);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入单个int类型数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <param name="Value"></param>
|
|||
|
|
public void WriteDReg(string iAddr, string Value)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
OperateResult result = omronCipNet.Write(iAddr, Value);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入单个int类型数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <param name="Value"></param>
|
|||
|
|
public void WriteDReg(string iAddr, int Value)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
OperateResult result = omronCipNet.Write(iAddr, Value);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 批量写入int类型数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <param name="Value"></param>
|
|||
|
|
public void WriteDReg(string iAddr, int[] Value)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
OperateResult result = omronCipNet.Write(iAddr, Value);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 批量写入ushort类型数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <param name="Value"></param>
|
|||
|
|
public void WriteDReg(string iAddr, short[] Value)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
OperateResult result = omronCipNet.Write(iAddr, Value);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < Value.Length; i++)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {Value[i]}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < Value.Length; i++)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {Value[i]}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写入单个Short类型数据
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <param name="Value"></param>
|
|||
|
|
public void WriteDReg(string iAddr, short Value)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
OperateResult result = omronCipNet.Write(iAddr, Value);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 写BOOL
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="iAddr"></param>
|
|||
|
|
/// <param name="Value"></param>
|
|||
|
|
public void WriteDReg(string iAddr, bool Value)
|
|||
|
|
{
|
|||
|
|
string type = iAddr.Substring(0, 1);
|
|||
|
|
if (type != "D" && type != "W")
|
|||
|
|
{
|
|||
|
|
AddLog(lstSend, 2, "暂只支持D,W存储区");
|
|||
|
|
}
|
|||
|
|
else if (IsConnected)
|
|||
|
|
{
|
|||
|
|
OperateResult result = omronCipNet.Write(iAddr, Value);
|
|||
|
|
if (result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 0, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
AddLog(lstResWrite, 2, $"{iAddr} --> {Value}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 是否启用心跳消息
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void cbHeartBeat_CheckedChanged(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
if (cbHeartBeat.Checked)
|
|||
|
|
{
|
|||
|
|
HeartBeat = true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
HeartBeat = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 保存配置
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void btnSaveConfig_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
PlcConfig.Index = Index;
|
|||
|
|
PlcConfig.IP = txtIP.Text.Trim();
|
|||
|
|
PlcConfig.Port = Convert.ToInt32(txtPort.Text.Trim());
|
|||
|
|
PlcConfig.HeartBeat = cbHeartBeat.Checked;
|
|||
|
|
PlcConfig.HeartAddr = txtHeartAddr.Text.Trim();
|
|||
|
|
PlcConfig.JobCount = JobCount;
|
|||
|
|
PlcConfig.ScanTime = ScanTime;
|
|||
|
|
PlcConfig.Solt= Convert.ToInt32(txtSolt.Text.Trim());
|
|||
|
|
OnSaveParams(Index, 0);
|
|||
|
|
AddLog(lstRecv, 0, "保存参数成功");
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
AddLog(lstRecv, 1, "保存参数失败" + ex.Message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 日志显示
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="lstView"></param>
|
|||
|
|
/// <param name="type"></param>
|
|||
|
|
/// <param name="info"></param>
|
|||
|
|
private void AddLog(ListView lstView, int type, string info)
|
|||
|
|
{
|
|||
|
|
ListViewItem lst = new ListViewItem(" " + CurrentTime, type);
|
|||
|
|
lst.SubItems.Add(info);
|
|||
|
|
if (base.InvokeRequired)
|
|||
|
|
{
|
|||
|
|
Invoke((Action)delegate
|
|||
|
|
{
|
|||
|
|
lstView.Items.Insert(0, lst);
|
|||
|
|
if (lstView.Items.Count > 2000)
|
|||
|
|
{
|
|||
|
|
lstView.Items.Clear();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (lstView.Items.Count > 2000)
|
|||
|
|
{
|
|||
|
|
lstView.Items.Clear();
|
|||
|
|
}
|
|||
|
|
lstView.Items.Insert(0, lst);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="val"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private bool[] GetBoolArray(string val)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
List<bool> Result = new List<bool>();
|
|||
|
|
if (val.Contains(','))
|
|||
|
|
{
|
|||
|
|
string[] str = Regex.Split(val, ",", RegexOptions.IgnoreCase);
|
|||
|
|
string[] array = str;
|
|||
|
|
foreach (string item in array)
|
|||
|
|
{
|
|||
|
|
Result.Add(item.ToLower() == "true" || item.ToLower() == "1");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Result.Add(val.ToLower() == "true" || val.ToLower() == "1");
|
|||
|
|
}
|
|||
|
|
return Result.ToArray();
|
|||
|
|
}
|
|||
|
|
catch (Exception)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private short[] GetShortArray(string val)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
List<short> Result = new List<short>();
|
|||
|
|
if (val.Contains(','))
|
|||
|
|
{
|
|||
|
|
string[] str = Regex.Split(val, ",", RegexOptions.IgnoreCase);
|
|||
|
|
string[] array = str;
|
|||
|
|
foreach (string item in array)
|
|||
|
|
{
|
|||
|
|
Result.Add(Convert.ToInt16(item));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Result.Add(Convert.ToInt16(val));
|
|||
|
|
}
|
|||
|
|
return Result.ToArray();
|
|||
|
|
}
|
|||
|
|
catch (Exception)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private int[] GetIntArray(string val)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
List<int> Result = new List<int>();
|
|||
|
|
if (val.Contains(','))
|
|||
|
|
{
|
|||
|
|
string[] str = Regex.Split(val, ",", RegexOptions.IgnoreCase);
|
|||
|
|
string[] array = str;
|
|||
|
|
foreach (string item in array)
|
|||
|
|
{
|
|||
|
|
Result.Add(Convert.ToInt32(item));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Result.Add(Convert.ToInt32(val));
|
|||
|
|
}
|
|||
|
|
return Result.ToArray();
|
|||
|
|
}
|
|||
|
|
catch (Exception)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private float[] GetFloatArray(string val)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
List<float> Result = new List<float>();
|
|||
|
|
if (val.Contains(','))
|
|||
|
|
{
|
|||
|
|
string[] str = Regex.Split(val, ",", RegexOptions.IgnoreCase);
|
|||
|
|
string[] array = str;
|
|||
|
|
foreach (string item in array)
|
|||
|
|
{
|
|||
|
|
Result.Add(Convert.ToSingle(item));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Result.Add(Convert.ToSingle(val));
|
|||
|
|
}
|
|||
|
|
return Result.ToArray();
|
|||
|
|
}
|
|||
|
|
catch (Exception)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 清除消息
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void btnClearRecv_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
lstRecv.Items.Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 数据接受委托事件
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="Index"></param>
|
|||
|
|
/// <param name="msg"></param>
|
|||
|
|
/// <param name="resByte"></param>
|
|||
|
|
public void OnReceive(int Index, string msg, OperateResult<byte[]> resByte)
|
|||
|
|
{
|
|||
|
|
if (this.ReceiveEvent != null)
|
|||
|
|
{
|
|||
|
|
this.ReceiveEvent(Index, msg, resByte);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 心跳消息委托事件
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="b"></param>
|
|||
|
|
public void OnUpHeartBeat(bool b)
|
|||
|
|
{
|
|||
|
|
if (this.UpHeartBeatEvent != null)
|
|||
|
|
{
|
|||
|
|
this.UpHeartBeatEvent(b);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 保存信息委托事件
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="plcIndex"></param>
|
|||
|
|
/// <param name="trgIndex"></param>
|
|||
|
|
public void OnSaveParams(int plcIndex, int trgIndex)
|
|||
|
|
{
|
|||
|
|
if (this.SaveParamsEvent != null)
|
|||
|
|
{
|
|||
|
|
this.SaveParamsEvent(plcIndex, trgIndex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 关闭读取PLC数据
|
|||
|
|
/// </summary>
|
|||
|
|
public void Shutdown()
|
|||
|
|
{
|
|||
|
|
if (omronCipNet != null)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
mCTSRecv.Cancel();
|
|||
|
|
mCTSHeart.Cancel();
|
|||
|
|
}
|
|||
|
|
catch (Exception)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 链接PLC开始启动
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void btnStart_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
if (!IsRun)
|
|||
|
|
{
|
|||
|
|
Connect();
|
|||
|
|
OmronStart(true);
|
|||
|
|
IsRun = true;
|
|||
|
|
btnStart.Text = "停止";
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ConnectClose();
|
|||
|
|
OmronStart(false);
|
|||
|
|
IsRun = false;
|
|||
|
|
btnStart.Text = "启动";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void cbDispCurrent_CheckedChanged(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
if (cbDispCurrent.Checked)
|
|||
|
|
{
|
|||
|
|
DispCurrent = true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
DispCurrent = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 心跳消息赋值
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="sender"></param>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
private void txtHeartAddr_TextChanged(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
_heartAddr = txtHeartAddr.Text;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void button1_Click(object sender, EventArgs e)
|
|||
|
|
{
|
|||
|
|
//OperateResult<OmronCpuUnitData> operateResult = omron_finsnet.ReadCpuUnitData();
|
|||
|
|
//if (operateResult.IsSuccess)
|
|||
|
|
//{
|
|||
|
|
// txtReadResultTest.Text = operateResult.Content.ToJsonString();
|
|||
|
|
//}
|
|||
|
|
//else
|
|||
|
|
//{
|
|||
|
|
// MessageBox.Show("read failed:" + operateResult.Message);
|
|||
|
|
//}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|