Commit 52095453 authored by 潘栩锋's avatar 潘栩锋 🚴

完成 PLCLink

parent 23c17d7b
......@@ -84,6 +84,7 @@
<Compile Include="IService\IHeatCell.cs" />
<Compile Include="IService\IHeatCheck.cs" />
<Compile Include="IService\IPLCLink.cs" />
<Compile Include="Server\PLCLink.cs" />
<Compile Include="Server\SnapShotBuf.cs" />
<Compile Include="Server\TDGage.cs" />
</ItemGroup>
......
......@@ -657,11 +657,10 @@ namespace FLY.FeedbackRenZiJia.Server
list.Add(heat);
}
hmi.SetHeat(list);
hmi.HeatUpdate++;
if (hmi.HeatUpdate == 0)
hmi.HeatUpdate = 1;
UInt16 heatupdate = (UInt16)(hmi.HeatUpdate + 1);
if (heatupdate == 0)
heatupdate = 1;
hmi.HeatUpdate = heatupdate;
}
void Add(DateTime time, DateTime endtime, Misc.DIRECTION direction, TimeSpan period, int rotateCnt,
......
using FLY.Modbus;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace FLY.FeedbackRenZiJia.Server
{
public class PLCLink : IPLCLink
{
//D200 4x201 通道数量
//D201 4x202 设置值 更新
//D202 4x203 当前值 更新
//D400 4x401 设置值 160个
//D600 4x601 当前值 160个
//M3 0x4 风环开关
//M4 0x5 检测电流
FLY.Modbus.WithThread.ClientTCP mclient;
/// <summary>
/// 更新周期,单位ms,
/// </summary>
public int UpdateInterval = 100;
/// <summary>
/// 实际更新间隔
/// </summary>
public TimeSpan ActUpdateInterval { get; private set; }
#region 输出
/// <summary>
/// 加热通道数
/// </summary>
public UInt16 ChannelCnt
{
get => _channelCnt;
set
{
_channelCnt = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ChannelCnt"));
}
}
/// <summary>
/// 加热量更新
/// </summary>
public UInt16 HeatUpdate
{
get => _heatUpdate;
set {
_heatUpdate = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("HeatUpdate"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region 当前值
/// <summary>
/// 当前电流 有没?
/// </summary>
public bool HasElectricity { get; private set; }
/// <summary>
/// 风机是否启动?
/// </summary>
public bool HasFan { get; private set; }
/// <summary>
/// 当前值更新
/// </summary>
public UInt16 CurrUpdate { get; private set; }
#endregion
#region 状态
public int Errno { get; set; }
#endregion
bool IsRunning;
public PLCLink(IPEndPoint ep)
{
mclient = new Modbus.WithThread.ClientTCP(ep);
mclient.PropertyChanged += Client_PropertyChanged;
this.PropertyChanged += PLCLink_PropertyChanged;
}
class RegWrite
{
public PLCAddressArea dataArea;
public int addr;
public object val;
public RegWrite(PLCAddressArea dataArea, int addr, object val)
{
this.dataArea = dataArea;
this.addr = addr;
this.val = val;
}
}
List<RegWrite> rws = new List<RegWrite>();
private ushort _channelCnt;
private ushort _heatUpdate;
private void PLCLink_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "ChannelCnt")
{
RegWrite regWrite = new RegWrite(PLCAddressArea.Register, 200, new UInt16[] { ChannelCnt });
lock (rws)
{
rws.Add(regWrite);
}
}
else if (e.PropertyName == "HeatUpdate")
{
RegWrite regWrite = new RegWrite(PLCAddressArea.Register, 201, new UInt16[] { HeatUpdate });
lock (rws)
{
rws.Add(regWrite);
}
}
}
private void Client_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsConnected")
{
if (!mclient.IsConnected)
{
rws.Clear();
}
else
{
Start();
}
}
}
void Start()
{
if (IsRunning)
return;
Task.Factory.StartNew(OnPoll_update);
}
void OnPoll_update()
{
IsRunning = true;
Stopwatch stopwatch = new Stopwatch();
while (mclient.IsConnected)
{
if (stopwatch.ElapsedMilliseconds >= UpdateInterval)
{
//检查上次更新周期是否完成
ActUpdateInterval = stopwatch.Elapsed;
stopwatch.Restart();
if (!UpdateReadData())
return;//连接断开,终止更新线程
}
//输出写入数据
if (!UpdateWriteData())
return;//连接断开,终止更新线程
Thread.Sleep(100);
}
IsRunning = false;
}
bool UpdateReadData()
{
//M3 0x4 风环开关
//M4 0x5 检测电流
if (!mclient.Do_01(3, 2, out IEnumerable<bool> values))
return false;
HasFan = values.ElementAt(0);
HasElectricity = values.ElementAt(0);
return true;
}
bool UpdateWriteData()
{
while (true)
{
RegWrite rw;
lock (rws)
{
if (rws.Count() == 0)
break;
rw = rws.First();
rws.RemoveAt(0);
}
switch (rw.dataArea)
{
case PLCAddressArea.Register:
if (!mclient.Do_10((UInt16)rw.addr, (IEnumerable<UInt16>)rw.val))
return false;
break;
}
}
return true;
}
/// <summary>
/// 设置加热量
/// </summary>
/// <param name="values"></param>
public void SetHeat(IEnumerable<UInt16> values)
{
UInt16[] buf = values.ToArray();
RegWrite regWrite = new RegWrite(PLCAddressArea.Register, 400, buf);
lock (rws)
{
rws.Add(regWrite);
}
}
/// <summary>
/// 获取当前值
/// </summary>
/// <returns></returns>
public IEnumerable<UInt16> GetCurr()
{
return null;
}
}
}
......@@ -24,8 +24,12 @@ namespace FLY.Modbus.WithThread
/// </summary>
public TimeSpan ActUpdateInterval { get; private set; }
/// <summary>
/// 工作中
/// </summary>
public bool IsRunning { get; private set; }
private Stopwatch mStopwatch = new Stopwatch();
class RegWrite
{
public PLCAddressArea dataArea;
......@@ -55,10 +59,7 @@ namespace FLY.Modbus.WithThread
mclient = clienttcp;
mclient.PropertyChanged += Mclient_PropertyChanged;
if (mclient.IsConnected)
{
Task.Factory.StartNew(OnPoll_update);
}
Start();
}
......@@ -83,20 +84,31 @@ namespace FLY.Modbus.WithThread
}
rws.Clear();
}
else
{
Start();
}
}
}
void Start()
{
if (IsRunning)
return;
Task.Factory.StartNew(OnPoll_update);
}
void OnPoll_update()
{
mStopwatch.Restart();
IsRunning = true;
Stopwatch stopwatch = new Stopwatch();
while (mclient.IsConnected)
{
if (mStopwatch.ElapsedMilliseconds >= UpdateInterval)
if (stopwatch.ElapsedMilliseconds >= UpdateInterval)
{
//检查上次更新周期是否完成
ActUpdateInterval = mStopwatch.Elapsed;
mStopwatch.Restart();
ActUpdateInterval = stopwatch.Elapsed;
stopwatch.Restart();
if (!UpdateReadData())
return;//连接断开,终止更新线程
......@@ -106,6 +118,7 @@ namespace FLY.Modbus.WithThread
return;//连接断开,终止更新线程
Thread.Sleep(0);
}
IsRunning = false;
}
/// <summary>
......@@ -178,6 +191,113 @@ namespace FLY.Modbus.WithThread
}
}
}
/// <summary>
/// 是从PLC读取数据后;
/// 设置Modbus的值,会改变相应命名数据的值,并产生通知
/// </summary>
/// <param name="dataarea">coil or register</param>
/// <param name="addr">地址</param>
/// <param name="value">值</param>
/// <returns></returns>
public override void SetModbusData(PLCAddressArea dataarea, int addr, object value)
{
switch (dataarea)
{
case PLCAddressArea.Register:
{
IEnumerable<UInt16> vals = (IEnumerable<UInt16>)value;
//找寄存器
int endAddr = addr + vals.Count() - 1;
RegisterData area_regs = (RegisterData)mAreaManager[1];
for (int i = 0; i < area_regs.regs.Count(); i++)
{
if (endAddr < area_regs.regs[i].dr.addr)
{
//在前面
break;
}
else if (addr <= area_regs.regs[i].EndAddr)//有交集
{
int addr_act = Math.Max(addr, area_regs.regs[i].dr.addr);
int endAddr_act = Math.Min(endAddr, area_regs.regs[i].EndAddr);
int num_act = endAddr_act - addr_act + 1;
for (int j = 0; j < num_act; j++)
{
int idx1 = addr_act - area_regs.regs[i].dr.addr + j;
int idx2 = addr_act - addr + j;
if (area_regs.regs[i].value[idx1] != vals.ElementAt(idx2))
{
area_regs.regs[i].value[idx1] = vals.ElementAt(idx2);
area_regs.regs[i].changed = true;
}
}
if (endAddr_act == area_regs.regs[i].EndAddr)
{
if (area_regs.regs[i].changed)
{
area_regs.regs[i].changed = false;
DataToRegs dr = area_regs.regs[i].dr;
//触发事件
dr.value = RegTypeConverter.ToObject(
area_regs.regs[i].value, dr.type, dr.scale);
NotifyNameDataChanged(dr.owner, dr.propertyName);
}
}
}
else
{
//在后面
}
}
}
break;
case PLCAddressArea.Coil:
{
IEnumerable<bool> vals = (IEnumerable<bool>)value;
//找寄存器
int endAddr = addr + vals.Count() - 1;
CoilData area_coils = mAreaManager[0] as CoilData;
for (int i = 0; i < area_coils.regs.Count(); i++)
{
if (endAddr < area_coils.regs[i].dr.addr)
{
//在前面
break;
}
else if (addr <= area_coils.regs[i].dr.addr)//有交集
{
int addr_act = area_coils.regs[i].dr.addr;
int idx2 = addr_act - addr;
if (area_coils.regs[i].value != vals.ElementAt(idx2))
{
area_coils.regs[i].value = vals.ElementAt(idx2);
DataToRegs dr = area_coils.regs[i].dr;
//触发事件
dr.value = area_coils.regs[i].value;
NotifyNameDataChanged(dr.owner, dr.propertyName);
}
}
else
{
//在后面
}
}
}
break;
}
}
/// <summary>
/// 提取全部写命令缓冲区 输出
/// </summary>
......@@ -191,6 +311,7 @@ namespace FLY.Modbus.WithThread
if (rws.Count() == 0)
break;
rw = rws.First();
rws.RemoveAt(0);
}
switch (rw.dataArea)
......@@ -207,11 +328,6 @@ namespace FLY.Modbus.WithThread
}
//更新 本地的 PLC 数据
SetModbusData(rw.dataArea, rw.addr, rw.val);
lock (rws)
{
rws.Remove(rw);
}
}
return true;
}
......
This diff is collapsed.
$root_path = $PSScriptRoot
$src_path = $root_path + "\WS_LP.xml"
$dest_dir = $root_path + "\..\..\..\..\Project.FLY.Weight\FLY.Weight.UI.Server\bin\Debug\Gage1"
$dest_path = $dest_dir + "\WS.xml"
if(-not (Test-Path $dest_dir))
{
echo $dest_dir
mkdir $dest_dir
}
echo WS.xml
cp $src_path $dest_path
echo Ƴɹ
pause
\ No newline at end of file
......@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
StartupUri="Window1.xaml">
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment