change - PLC 交互

foamRearStore
wenjy 1 year ago
parent bd8acc5d25
commit 7482ecd3fb

Binary file not shown.

@ -1,5 +1,7 @@
using HighWayIot.Log4net;
using HighWayIot.Config;
using HighWayIot.Log4net;
using HighWayIot.Plc;
using HighWayIot.Plc.Impl;
using HighWayIot.Repository.domain;
using HighWayIot.Repository.service;
using HighWayIot.Repository.service.Impl;
@ -14,6 +16,7 @@ namespace Aucma.Scada.Business
public class MainBusiness
{
private static readonly Lazy<MainBusiness> lazy = new Lazy<MainBusiness>(() => new MainBusiness());
public static MainBusiness Instance
{
get
@ -21,12 +24,20 @@ namespace Aucma.Scada.Business
return lazy.Value;
}
}
public MainBusiness()
private AppConfig appConfig = AppConfig.Instance;
private PlcConfig plcConfig = PlcConfig.Instance;
private PlcPool plcPool = PlcPool.Instance;
private MainBusiness()
{
//初始化扫码器
//初始化PLC
//初始化Plc
plcPool.InitPlc("MelsecBinaryPlc", plcConfig.shell_Plc_Ip, plcConfig.shell_Plc_Port, appConfig.shellStoreCode);
plcPool.InitPlc("MelsecBinaryPlc", plcConfig.liner_Plc_Ip, plcConfig.liner_Plc_Port, appConfig.linerStoreCode);
//初始化货道信息,保证系统内的库存信息与实物一致
}

@ -73,6 +73,7 @@ namespace Aucma.Scada.Business
private OutStoreBusiness()
{
assemblyPlanBusiness.NextPassExecutePlanInfoEvent += PlanHandle;
taskHandleBusiness.OutStoreFinsihEvent += TaskFeedback;
StartPassDown();
}
@ -261,6 +262,10 @@ namespace Aucma.Scada.Business
/// <param name="e"></param>
private void PassDownTaskInfo()
{
string shellCode = string.Empty;
string linerCode = string.Empty;
string taskCode = string.Empty;
int iFlag= 0;
completedTasks = 0;
//获取待执行的出库任务下发至PLC,并将任务状态改为执行中
@ -272,22 +277,61 @@ namespace Aucma.Scada.Business
foreach (var item in taskInfoList)
{
//taskHandleBusiness.SendOutStoreTask(item);
PrintLogInfoMessage($"下发出库任务:{item.taskCode};仓库{item.storeCode};货道:{item.spaceCode}");
taskCode = item.taskCode;
if (item.storeCode == appConfig.shellStoreCode)
{
if (taskHandleBusiness.SendShellTask_OutStore(item))
{
PrintLogInfoMessage($"下发箱壳出库任务:{item.taskCode};仓库{item.storeCode};货道:{item.spaceCode}等待PLC执行反馈");
item.taskStatus = 2;
iFlag++;
}
else
{
PrintLogInfoMessage($"箱壳出库任务:{item.taskCode}下发失败请排除PLC连接");
continue;
}
shellCode = item.materialCode;
}
else if(item.storeCode == appConfig.linerStoreCode)
{
if (taskHandleBusiness.SendLinerTask_OutStore(item))
{
PrintLogInfoMessage($"下发内胆出库任务:{item.taskCode};仓库{item.storeCode};货道:{item.spaceCode}等待PLC执行反馈");
item.taskStatus = 2;
iFlag++;
}
else
{
PrintLogInfoMessage($"内胆出库任务:{item.taskCode}下发失败请排除PLC连接");
continue;
}
linerCode = item.materialCode;
}
RefreshScanMateriaCodeEvent?.Invoke(item.materialCode, item.materialType, item.spaceName, item.storeCode);
}
if (semaphore.Wait(TimeSpan.FromSeconds(20)))
{
// 收到反馈
PrintLogInfoMessage("收到反馈,继续执行");
}
else
if(iFlag == taskInfoList.Count)
{
PrintLogInfoMessage("超时未反馈");
}
_taskInfoService.UpdateRangeTaskInfo(taskInfoList);
//if (semaphore.Wait(TimeSpan.FromSeconds(20)))
//{
// // 收到反馈
// PrintLogInfoMessage("收到反馈,继续执行");
//}
//else
//{
// PrintLogInfoMessage("超时未反馈");
//}
semaphore.Wait(); //一直堵塞直到信号量释放
PrintLogInfoMessage($"出库任务:{taskCode};执行完成,绑定箱壳条码:{shellCode};内胆条码:{linerCode}");
//semaphore.Wait(); //一直堵塞直到信号量释放
}
}
else
{
@ -311,17 +355,22 @@ namespace Aucma.Scada.Business
if(shellTaskInfo != null)
{
taskInfos.Add(shellTaskInfo);
//获取与箱壳任务匹配的内胆任务
RealTaskInfo linerTaskInfo = _taskInfoService.GetTaskInfoByTaskCode(shellTaskInfo.taskCode, appConfig.linerStoreCode);
taskInfos.Add(shellTaskInfo);
if (linerTaskInfo != null) taskInfos.Add(linerTaskInfo);
}
if(taskInfos.Count > 0)
else
{
taskInfos.ForEach(x => x.taskStatus = 2);
_taskInfoService.UpdateRangeTaskInfo(taskInfos);
RealTaskInfo linerInfo = _taskInfoService.GetTaskInfoByStoreCode(appConfig.linerStoreCode, 2);
if (linerInfo != null) taskInfos.Add(linerInfo);
}
//if(taskInfos.Count > 0)
//{
// taskInfos.ForEach(x => x.taskStatus = 2);
// _taskInfoService.UpdateRangeTaskInfo(taskInfos);
//}
}
catch(Exception ex)
{
@ -330,10 +379,27 @@ namespace Aucma.Scada.Business
return taskInfos;
}
/// <summary>
/// PLC任务执行反馈
/// </summary>
/// <param name="storeCode"></param>
/// <param name="taskCode"></param>
private void TaskFeedback(string storeCode, string taskCode)
{
if(storeCode == appConfig.shellStoreCode)
{
ShellTaskFeedback(taskCode);
}
else
{
LinerTaskFeedback(taskCode);
}
}
/// <summary>
/// 箱壳执行反馈
/// </summary>
private void ShellTaskFeedback()
private void ShellTaskFeedback(string taskCode)
{
Interlocked.Increment(ref completedTasks);
@ -341,13 +407,13 @@ namespace Aucma.Scada.Business
PrintLogInfoMessage("箱壳执行完成,自动释放信号量");
OutStoreFinish("", appConfig.shellStoreCode);
OutStoreFinish(taskCode, appConfig.shellStoreCode);
}
/// <summary>
/// 内胆执行反馈
/// </summary>
private void LinerTaskFeedback()
private void LinerTaskFeedback(string taskCode)
{
Interlocked.Increment(ref completedTasks);
@ -355,7 +421,7 @@ namespace Aucma.Scada.Business
PrintLogInfoMessage("内胆执行完成,自动释放信号量");
OutStoreFinish("", appConfig.linerStoreCode);
OutStoreFinish(taskCode, appConfig.linerStoreCode);
}
/// <summary>
@ -386,6 +452,9 @@ namespace Aucma.Scada.Business
var taskInfo = _taskInfoService.GetTaskInfoByTaskCode(taskCode, storeCode);
if (taskInfo != null)
{
//刷新界面
RefreshScanMateriaCodeEvent?.Invoke(string.Empty, string.Empty, string.Empty, taskInfo.storeCode);
var spaceInfo = _spaceInfoService.GetSpaceInfoBySpaceCode(taskInfo.storeCode, taskInfo.spaceCode);
if (spaceInfo != null)

@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Aucma.Scada.Business
@ -25,71 +26,348 @@ namespace Aucma.Scada.Business
}
}
public delegate void OutStoreFinsih(string storeCode,string taskCode);
public delegate void OutStoreFinsih(string storeCode, string taskCode);
public event OutStoreFinsih OutStoreFinsihEvent;
private IPlc _plc = new SiemensPlc();
/// <summary>
/// 字典存放PLC连接
/// </summary>
private Dictionary<string, IPlc> _plcDictionary = new Dictionary<string, IPlc>();
private LogHelper logHelper = LogHelper.Instance;
private AppConfig appConfig = AppConfig.Instance;
private PlcConfig plcConfig = PlcConfig.Instance;
private PlcPool _pool = PlcPool.Instance;
private string shellTaskCode = string.Empty;
private string linerTaskCode = string.Empty;
private TaskHandleBusiness()
{
//_plcDictionary.Add(appConfig.shellStoreCode, new MelsecBinaryPlc());
//_plcDictionary.Add(appConfig.linerStoreCode, new MelsecBinaryPlc());
//var shellPlc = _plcDictionary[appConfig.shellStoreCode].Connect(plcConfig.shell_Plc_Ip, plcConfig.shell_Plc_Port);
//var linerPlc = _plcDictionary[appConfig.linerStoreCode].Connect(plcConfig.liner_Plc_Ip, plcConfig.liner_Plc_Port);
_plcDictionary = _pool.GetAll();
}
public void Inite()
#region 箱壳出库任务下发处理
/// <summary>
/// 箱壳出库任务下发
/// </summary>
/// <param name="taskInfo"></param>
public bool SendShellTask_OutStore(RealTaskInfo taskInfo)
{
_plc.Connect("127.0.0.1", 124);
bool result = false;
try
{
IPlc _plc = _plcDictionary[taskInfo.storeCode];
if (_plc != null)
{
if (_plc.IsConnected)
{
//写入货道号
_plc.writeStringByAddress(plcConfig.out_shell_spaceCode, taskInfo.spaceCode);
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_shell_amount, taskInfo.planAmount);
//写入应答字
_plc.writeInt32ByAddress(plcConfig.out_shell_answer, 1);
//写入任务号
_plc.writeStringByAddress(plcConfig.out_shell_task, taskInfo.taskCode);
//写入完成后读取应答字进行复位
ReadShellAnswer_OutStore(taskInfo.taskCode);
result = true;
}
else
{
logHelper.Info($"仓库{taskInfo.storeCode}PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("箱壳出库任务下发异常", ex);
}
return result;
}
public bool SendOutStoreTask(RealTaskInfo realTaskInfo)
/// <summary>
/// 读取箱壳出库应答
/// </summary>
private void ReadShellAnswer_OutStore(string taskCode)
{
bool result = false;
string spaceCode = string.Empty;
string amount = string.Empty;
string taskCode = string.Empty;
string answer = string.Empty;
try
lock (string.Empty)
{
bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.shellStoreCode];
try
{
Task.Run(() =>
{
if (_plc != null)
{
if (_plc.IsConnected)
{
do
{
//读取PLC应答字为2时上位机清空写入的出库内容
if (_plc.readInt32ByAddress(plcConfig.out_shell_answer) == 2)
{
//写入货道号
_plc.writeStringByAddress(plcConfig.out_shell_spaceCode, string.Empty);
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_shell_amount, 0);
//写入应答字
_plc.writeInt32ByAddress(plcConfig.out_shell_answer, 0);
//写入任务号
_plc.writeStringByAddress(plcConfig.out_shell_task, string.Empty);
isFlag = false;
ReadShellFinish_OutStore(taskCode);
}
if(realTaskInfo.storeCode == appConfig.shellStoreCode)
Thread.Sleep(5000);
} while (isFlag);
}
else
{
logHelper.Info($"仓库{appConfig.shellStoreCode}PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空通过{appConfig.shellStoreCode}未获取到该仓库对应的PLC信息");
}
});
}
catch (Exception ex)
{
spaceCode = plcConfig.out_shell_spaceCode;
amount = plcConfig.out_shell_amount;
taskCode = plcConfig.out_shell_task;
}else if (realTaskInfo.storeCode == appConfig.linerStoreCode)
logHelper.Error("读取箱壳出库应答字异常", ex);
}
}
}
/// <summary>
/// 读取箱壳出库完成
/// </summary>
private void ReadShellFinish_OutStore(string taskCode)
{
lock (string.Empty)
{
bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.shellStoreCode];
shellTaskCode = taskCode;
try
{
Task.Run(() =>
{
if (_plc != null)
{
if (_plc.IsConnected)
{
do
{
//读取PLC出库任务完成
if (_plc.readInt32ByAddress(plcConfig.out_shell_finish) == 1)
{
_plc.writeInt32ByAddress(plcConfig.out_shell_finish, 0);
//string taskCode = _plc.readStringByAddress(plcConfig.out_shell_task, 10);
OutStoreFinsihEvent?.Invoke(appConfig.shellStoreCode, taskCode);
isFlag = false;
}
Thread.Sleep(5000);
} while (isFlag);
}
else
{
logHelper.Info($"仓库{appConfig.shellStoreCode}PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空通过{appConfig.shellStoreCode}未获取到该仓库对应的PLC信息");
}
});
}
catch (Exception ex)
{
spaceCode = plcConfig.out_liner_spaceCode;
amount = plcConfig.out_liner_amount;
taskCode = plcConfig.out_liner_task;
logHelper.Error("读取箱壳出库出库完成异常", ex);
}
}
}
#endregion
//写入货道号
_plc.writeStringByAddress(spaceCode, realTaskInfo.spaceCode);
//写入出库数量
_plc.writeInt32ByAddress(amount, realTaskInfo.planAmount);
//写入任务号
_plc.writeStringByAddress(taskCode,realTaskInfo.taskCode);
//写入应答字
_plc.writeInt32ByAddress(answer, 1);
#region 内胆出库任务处理
/// <summary>
/// 内胆出库任务下发
/// </summary>
/// <param name="taskInfo"></param>
public bool SendLinerTask_OutStore(RealTaskInfo taskInfo)
{
bool result = false;
try
{
IPlc _plc = _plcDictionary[taskInfo.storeCode];
if (_plc != null)
{
if (_plc.IsConnected)
{
//写入货道号
_plc.writeStringByAddress(plcConfig.out_liner_spaceCode, taskInfo.spaceCode);
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_liner_amount, taskInfo.planAmount);
//写入应答字
_plc.writeInt32ByAddress(plcConfig.out_liner_answer, 1);
//写入任务号
_plc.writeStringByAddress(plcConfig.out_liner_task, taskInfo.taskCode);
result = true;
//写入完成后读取应答字进行复位
ReadLinerAnswer_OutStore(taskInfo.taskCode);
result = true;
}
else
{
logHelper.Info($"仓库{taskInfo.storeCode}PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息");
}
}
catch(Exception ex)
catch (Exception ex)
{
logHelper.Error("出库任务下发异常", ex);
logHelper.Error("内胆出库任务下发异常", ex);
}
return result;
}
private void ReadPlc()
/// <summary>
/// 读取内胆出库应答
/// </summary>
private void ReadLinerAnswer_OutStore(string taskCode)
{
lock (string.Empty)
{
bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.shellStoreCode];
linerTaskCode = taskCode;
try
{
Task.Run(() =>
{
if (_plc != null)
{
if (_plc.IsConnected)
{
do
{
//读取PLC应答字为2时上位机清空写入的出库内容
if (_plc.readInt32ByAddress(plcConfig.out_liner_answer) == 2)
{
//写入货道号
_plc.writeStringByAddress(plcConfig.out_liner_spaceCode, string.Empty);
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_liner_amount, 0);
//写入应答字
_plc.writeInt32ByAddress(plcConfig.out_liner_answer, 0);
//写入任务号
_plc.writeStringByAddress(plcConfig.out_liner_task, string.Empty);
isFlag = false;
Thread.Sleep(5000);
ReadLinerFinish_OutStore(taskCode);
}
} while (isFlag);
}
else
{
logHelper.Info($"仓库{appConfig.linerStoreCode}PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空通过{appConfig.linerStoreCode}未获取到该仓库对应的PLC信息");
}
});
}
catch (Exception ex)
{
logHelper.Error("读取内胆出库应答字异常", ex);
}
}
}
/// <summary>
/// 读取内胆出库完成
/// </summary>
private void ReadLinerFinish_OutStore(string taskCode)
{
if(_plc.readInt32ByAddress("") == 1) // 读取PLC出库应答字出库完成后读取任务号
lock (string.Empty)
{
string taskCode = _plc.readStringByAddress("", (ushort)12);
OutStoreFinsihEvent?.Invoke(appConfig.shellStoreCode, taskCode);
try
{
Task.Run(() =>
{
bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.linerStoreCode];
if (_plc != null)
{
if (_plc.IsConnected)
{
do
{
//读取PLC出库任务完成
if (_plc.readInt32ByAddress(plcConfig.out_liner_finish) == 1)
{
_plc.writeInt32ByAddress(plcConfig.out_liner_finish, 0);
//string taskCode = _plc.readStringByAddress(plcConfig.out_liner_task, 10);
OutStoreFinsihEvent?.Invoke(appConfig.linerStoreCode, taskCode);
isFlag = false;
Thread.Sleep(5000);
}
} while (isFlag);
}
else
{
logHelper.Info($"仓库{appConfig.linerStoreCode}PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空通过{appConfig.linerStoreCode}未获取到该仓库对应的PLC信息");
}
});
}
catch (Exception ex)
{
logHelper.Error("读取内胆出库完成异常", ex);
}
}
}
#endregion
}
}

@ -6,7 +6,7 @@
xmlns:local="clr-namespace:Aucma.Scada.UI"
mc:Ignorable="d"
Title="SCADA" Height="1080" Width="1920" Icon="Icon.png"
WindowState="Maximized" WindowStyle="None" ResizeMode="NoResize" Topmost="False"
WindowState="Maximized" ResizeMode="NoResize" Topmost="False"
>
<!--WindowState="Maximized" WindowStyle="None" ResizeMode="NoResize"Topmost="True"-->

@ -0,0 +1,17 @@
[plcSystem]
箱壳PLCIP=127.0.0.1
箱壳PLC端口=6000
内胆PLCIP=127.0.0.1
内胆PLC端口=6000
[shell_outStore_address]
出库货道号=M101
出库数量=M102
出库应答字=M103
出库任务号=M104
出库完成=M105
[liner_outStore_address]
出库货道号=M201
出库数量=M202
出库应答字=M203
出库任务号=M204
出库完成=M205

@ -1,4 +1,4 @@
#pragma checksum "..\..\MainWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "53ECC8664EAD4ED3B35A7728C0718F75FF25D4DA284A78D25AF8ADDDB5DA2F97"
#pragma checksum "..\..\MainWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "761197E72019FA48DD888520668F10CC0A0310CFF8A6F9336B14C0A351ACC259"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。

@ -1,4 +1,4 @@
#pragma checksum "..\..\MainWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "53ECC8664EAD4ED3B35A7728C0718F75FF25D4DA284A78D25AF8ADDDB5DA2F97"
#pragma checksum "..\..\MainWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "761197E72019FA48DD888520668F10CC0A0310CFF8A6F9336B14C0A351ACC259"
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。

@ -1,4 +1,5 @@
using Aucma.Scada.UI.Page.AssemblyPlan;
using Aucma.Scada.Business;
using Aucma.Scada.UI.Page.AssemblyPlan;
using Aucma.Scada.UI.Page.InStoreInfo;
using Aucma.Scada.UI.Page.InventoryInfo;
using Aucma.Scada.UI.Page.OutStoreInfo;
@ -26,6 +27,8 @@ namespace Aucma.Scada.UI.viewModel
private readonly InventoryInfoControl inventoryInfoControl = new InventoryInfoControl();
private readonly AssemblyPlanControl assemblyPlanControl = new AssemblyPlanControl();
private MainBusiness mainBusiness = MainBusiness.Instance;
public MainViewModel()
{
ControlOnClickCommand = new RelayCommand<object>(obj => ControlOnClick(obj));

@ -168,7 +168,7 @@ namespace HighWayIot.Common
byte[] intBytes = new byte[floatBytes.Length / 2];
for (int i = 0; i < intBytes.Length; i++)
{
intBytes[i] = floatBytes[i * 2 + 1];
intBytes[i] = floatBytes[i * 2 ];
}
return intBytes;
}

@ -10,7 +10,7 @@ namespace HighWayIot.Config
public sealed class PlcConfig
{
private static IniHelper iniHelper = new IniHelper(System.Environment.CurrentDirectory + "/config/Plc.InI");
private static IniHelper iniHelper = new IniHelper(System.Environment.CurrentDirectory + "/config/Plc.Ini");
private static readonly Lazy<PlcConfig> lazy = new Lazy<PlcConfig>(() => new PlcConfig());
@ -28,6 +28,46 @@ namespace HighWayIot.Config
{
}
#region PLC基础参数
/// <summary>
/// 箱壳PLCIP
/// </summary>
public string shell_Plc_Ip
{
get { return iniHelper.IniReadValue("plcSystem", "箱壳PLCIP"); }
set { iniHelper.IniWriteValue("plcSystem", "箱壳PLCIP", value); }
}
/// <summary>
/// 箱壳PLC端口
/// </summary>
public int shell_Plc_Port
{
get { return stringChange.ParseToInt(iniHelper.IniReadValue("plcSystem", "箱壳PLC端口")); }
set { iniHelper.IniWriteValue("plcSystem", "箱壳PLC端口", value.ToString()); }
}
/// <summary>
/// 内胆PLCIP
/// </summary>
public string liner_Plc_Ip
{
get { return iniHelper.IniReadValue("plcSystem", "内胆PLCIP"); }
set { iniHelper.IniWriteValue("plcSystem", "内胆PLCIP", value); }
}
/// <summary>
/// 内胆PLC端口
/// </summary>
public int liner_Plc_Port
{
get { return stringChange.ParseToInt(iniHelper.IniReadValue("plcSystem", "内胆PLC端口")); }
set { iniHelper.IniWriteValue("plcSystem", "内胆PLC端口", value.ToString()); }
}
#endregion
#region 箱壳出库地址
/// <summary>
/// 箱壳——出库货道号
/// </summary>
@ -46,6 +86,15 @@ namespace HighWayIot.Config
set { iniHelper.IniWriteValue("shell_outStore_address", "出库数量", value); }
}
/// <summary>
/// 箱壳——出库应答字
/// </summary>
public string out_shell_answer
{
get { return iniHelper.IniReadValue("shell_outStore_address", "出库应答字"); }
set { iniHelper.IniWriteValue("shell_outStore_address", "出库应答字", value); }
}
/// <summary>
/// 箱壳——出库任务号
/// </summary>
@ -55,6 +104,17 @@ namespace HighWayIot.Config
set { iniHelper.IniWriteValue("shell_outStore_address", "出库任务号", value); }
}
/// <summary>
/// 箱壳——出库完成
/// </summary>
public string out_shell_finish
{
get { return iniHelper.IniReadValue("shell_outStore_address", "出库完成"); }
set { iniHelper.IniWriteValue("shell_outStore_address", "出库完成", value); }
}
#endregion
#region 内胆出库地址
/// <summary>
/// 内胆——出库货道号
/// </summary>
@ -63,7 +123,7 @@ namespace HighWayIot.Config
get { return iniHelper.IniReadValue("liner_outStore_address", "出库货道号"); }
set { iniHelper.IniWriteValue("liner_outStore_address", "出库货道号", value); }
}
/// <summary>
/// 内胆——出库数量
/// </summary>
@ -73,6 +133,15 @@ namespace HighWayIot.Config
set { iniHelper.IniWriteValue("liner_outStore_address", "出库数量", value); }
}
/// <summary>
/// 内胆——出库应答字
/// </summary>
public string out_liner_answer
{
get { return iniHelper.IniReadValue("liner_outStore_address", "出库应答字"); }
set { iniHelper.IniWriteValue("liner_outStore_address", "出库应答字", value); }
}
/// <summary>
/// 内胆——出库任务号
/// </summary>
@ -82,5 +151,14 @@ namespace HighWayIot.Config
set { iniHelper.IniWriteValue("liner_outStore_address", "出库任务号", value); }
}
/// <summary>
/// 内胆——出库完成
/// </summary>
public string out_liner_finish
{
get { return iniHelper.IniReadValue("liner_outStore_address", "出库完成"); }
set { iniHelper.IniWriteValue("liner_outStore_address", "出库完成", value); }
}
#endregion
}
}

@ -46,9 +46,11 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Impl\InovancePlc.cs" />
<Compile Include="Impl\MelsecBinaryPlc.cs" />
<Compile Include="Impl\OmronNJPlc.CS" />
<Compile Include="Impl\SiemensPlc.cs" />
<Compile Include="IPlc.cs" />
<Compile Include="PlcPool.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

@ -0,0 +1,444 @@
using HighWayIot.Common;
using HighWayIot.Log4net;
using HslCommunication;
using HslCommunication.Profinet.Melsec;
using HslCommunication.Profinet.Omron;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HighWayIot.Plc.Impl
{
/// <summary>
/// 三菱Q系列Plc-Binary
/// </summary>
public class MelsecBinaryPlc : IPlc
{
private LogHelper log = LogHelper.Instance;
private StringChange stringChange = StringChange.Instance;
private MelsecMcNet melsec_net = null;
public MelsecBinaryPlc()
{
if (!HslCommunication.Authorization.SetAuthorizationCode("ed1415f8-e06a-43ad-95f7-c04f7ae93b41"))
{
log.Info("HslCommunication 11.0.6.0激活失败");
return;
}
log.Info("HslCommunication 11.0.6.0激活成功");
this.melsec_net = new MelsecMcNet();
this.melsec_net.ConnectTimeOut = 2000;
}
public bool IsConnected { get; set; }
/// <summary>
/// 建立连接
/// </summary>
/// <param name="IP"></param>
/// <param name="port"></param>
/// <returns></returns>
public bool Connect(string IP, int port)
{
log.PlcLog("欧姆龙NJ系列PLC连接开始");
melsec_net.IpAddress = IP;
melsec_net.Port = port;
try
{
OperateResult connect = melsec_net.ConnectServer();
if (connect.IsSuccess)
{
this.IsConnected = true;
log.PlcLog("欧姆龙NJ系列PLC建立连接成功");
return true;
}
else
{
this.IsConnected = false;
log.PlcLog("欧姆龙NJ系列PLC建立连接失败");
return false;
}
}
catch (Exception ex)
{
this.IsConnected = false;
log.Error("欧姆龙NJ系列PLC建立连接异常", ex);
return false;
}
}
/// <summary>
/// 断开连接
/// </summary>
/// <returns></returns>
public bool DisConnect()
{
return melsec_net.ConnectClose().IsSuccess;
}
/// <summary>
/// 通过地址和长度读取PLC数据
/// </summary>
/// <param name="len"></param>
/// <param name="address"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public byte[] readValueByAddress(int len, string address)
{
//log.PlcLog("开始通过PLC地址和长度读取PLC数据");
try
{
OperateResult<byte[]> read = melsec_net.Read(address, (ushort)(len));
if (read.IsSuccess)
{
byte[] result = stringChange.ConvertFloatToINt(read.Content);
log.PlcLog(String.Format("通过地址和长度读取PLC数据成功{0}", stringChange.bytesToHexStr(result, result.Length)));
return result;
}
else
{
log.PlcLog("通过地址和长度读取PLC数据失败");
this.IsConnected = false;
return new byte[0];
}
}
catch (Exception ex)
{
log.Error("通过地址和长度读取PLC数据异常", ex);
this.IsConnected = false;
return new byte[0];
}
}
/// <summary>
/// 通过PLC地址写入int类型数据
/// </summary>
/// <param name="value"></param>
/// <param name="address"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool writeValueByAddress(int value, string address)
{
//log.PlcLog(String.Format("开始通过PLC地址{0}写入int类型数据{1}",address,value));
try
{
OperateResult operateResult = melsec_net.Write(address, Convert.ToInt32(value));
if (operateResult.IsSuccess)
{
log.PlcLog(String.Format("开始通过PLC地址{0}写入int类型数据{1}成功", address, value));
return true;
}
log.PlcLog(String.Format("开始通过PLC地址{0}写入int类型数据{1}失败!!!", address, value));
this.IsConnected = false;
return false;
}
catch (Exception ex)
{
log.Error("通过PLC地址写入int类型数据", ex);
this.IsConnected = false;
return false;
}
}
/// <summary>
/// 通过PLC地址清零数据
/// </summary>
/// <param name="address"></param>
/// <param name="len"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool resetByAddress(string address, int len)
{
//log.PlcLog(String.Format("开发通过PLC地址{0}清零数据", address));
try
{
byte[] write = new byte[len * 2];
for (int i = 0; i < len * 2; i++)
{
write[i] = 0;
}
OperateResult operateResult = melsec_net.Write(address, write);
if (operateResult.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}清零数据成功", address));
return true;
}
log.PlcLog(String.Format("通过PLC地址{0}清零数据失败!!!", address));
return false;
}
catch (Exception ex)
{
log.Error(String.Format("通过PLC地址{0}清零数据异常", address), ex);
return false;
}
}
/// <summary>
/// 通过PLC地址读取EA值
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public string readEaByAddress(string address)
{
//log.PlcLog(String.Format("通过PLC地址{0}读取EA值", address));
try
{
OperateResult<Byte[]> read = melsec_net.Read(address, (ushort)(8));
if (read.IsSuccess && read.Content != null)
{
string result = Convert.ToString(read.Content);
log.PlcLog(String.Format("通过PLC地址{0}读取EA值成功{1}", address, result));
return result;
}
else
{
log.PlcLog(String.Format("通过PLC地址{0}读取EA值失败", address));
this.IsConnected = false;
return "";
}
}
catch (Exception ex)
{
log.Error("通过PLC地址读取EA值异常", ex);
this.IsConnected = false;
return "";
}
}
/// <summary>
/// 通过PLC地址读取交互信号
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public int readInteractiveSignal(string address)
{
//log.PlcLog(String.Format("开始通过PLC地址{0}读取交互信号", address));
try
{
OperateResult<short> read = melsec_net.ReadInt16(address);
if (read.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}读取交互信号成功:{1}", address, read.Content));
return read.Content;
}
log.PlcLog(String.Format("通过PLC地址{0}读取交互信号失败!!!", address));
this.IsConnected = false;
return 0;
}
catch (Exception ex)
{
log.Error("通过PLC地址读取交互信号异常", ex);
this.IsConnected = false;
return 0;
}
}
/// <summary>
/// 通过PLC地址读取int32类型数据
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public int readInt32ByAddress(string address)
{
//log.PlcLog(String.Format("开始通过PLC地址{0}读取int32类型数据",address));
try
{
OperateResult<short> read = melsec_net.ReadInt16(address);
if (read.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}读取int32类型数据成功{1}", address, read.Content));
return read.Content;
}
log.PlcLog(String.Format("通过PLC地址{0}读取int32类型数据失败", address));
this.IsConnected = false;
return 0;
}
catch (Exception ex)
{
log.Error("通过PLC地址读取int32类型数据异常", ex);
this.IsConnected = false;
return 0;
}
}
/// <summary>
/// 通过PLC地址写入int32类型数据
/// </summary>
/// <param name="address"></param>
/// <param name="value"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool writeInt32ByAddress(string address, int value)
{
log.PlcLog(String.Format("开始通过PLC地址{0}写入int32类型数据{1}", address, value));
try
{
OperateResult write = melsec_net.Write(address, short.Parse(Convert.ToString(value)));
if (write.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}写入int32类型数据{1}成功", address, value));
return true;
}
log.PlcLog(String.Format("通过PLC地址{0}写入int32类型数据{1}失败!!!", address, value));
this.IsConnected = false;
return false;
}
catch (Exception ex)
{
log.Error(String.Format("通过PLC地址{0}写入int32类型数据异常", address), ex);
this.IsConnected = false;
return false;
}
}
/// <summary>
/// 通过PLC地址写入String类型数据
/// </summary>
/// <param name="address"></param>
/// <param name="value"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool writeStringByAddress(string address, string value)
{
//log.PlcLog(String.Format("通过PLC地址{0}写入String类型数据{1}",address,value));
try
{
OperateResult operateResult = melsec_net.Write(address, value);
if (operateResult.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}写入String类型数据{1}成功", address, value));
return true;
}
log.PlcLog(String.Format("通过PLC地址{0}写入String类型数据{1}失败!!!", address, value));
//this.IsConnected = false;
return false;
}
catch (Exception ex)
{
log.Error(String.Format("通过PLC地址{0}写入String类型数据异常", address), ex);
//this.IsConnected = false;
return false;
}
}
/// <summary>
/// 通过PLC地址读取string类型数据
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public string readStringByAddress(string address, ushort length)
{
//log.PlcLog(String.Format("开始通过PLC地址{0}读取string类型数据", address));
try
{
OperateResult<String> read = melsec_net.ReadString(address, length);
if (read.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}读取string类型数据成功{1}", address, read.Content));
return read.Content;
}
log.PlcLog(String.Format("通过PLC地址{0}读取string类型数据失败", address));
this.IsConnected = false;
return "";
}
catch (Exception ex)
{
log.Error("通过PLC地址读取int32类型数据异常", ex);
return "";
}
}
/// <summary>
/// 通过PLC地址读取Bool类型数据
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool readBoolByAddress(string address)
{
//log.PlcLog(String.Format("开始通过PLC地址{0}读取bool类型数据", address));
try
{
OperateResult<bool> read = melsec_net.ReadBool(address);
if (read.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}读取bool类型数据成功{1}", address, read.Content));
return read.Content;
}
log.PlcLog(String.Format("通过PLC地址{0}读取bool类型数据失败", address));
this.IsConnected = false;
return false;
}
catch (Exception ex)
{
log.Error("通过PLC地址读取int32类型数据异常", ex);
this.IsConnected = false;
return false;
}
}
/// <summary>
/// 通过PLC地址写入Bool类型数据
/// </summary>
/// <param name="address"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool writeBoolByAddress(string address, bool value)
{
//log.PlcLog(String.Format("开始通过PLC地址{0}写入bool类型数据{1}", address, value));
try
{
OperateResult write = melsec_net.Write(address, short.Parse(stringChange.ParseToInt(value ? "1" : "0").ToString()));
if (write.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}写入bool类型数据{1}成功", address, value));
return true;
}
log.PlcLog(String.Format("通过PLC地址{0}写入bool类型数据{1}失败!!!", address, value));
this.IsConnected = false;
return false;
}
catch (Exception ex)
{
log.Error(String.Format("通过PLC地址{0}写入bool类型数据异常", address), ex);
this.IsConnected = false;
return false;
}
}
/// <summary>
/// 写入Double类型
/// </summary>
/// <param name="address"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool writeDoubleByAddress(string address, int value)
{
try
{
OperateResult write = melsec_net.Write(address, Convert.ToDouble(value));
if (write.IsSuccess)
{
log.PlcLog(String.Format("通过PLC地址{0}写入Double类型数据{1}成功", address, value));
return true;
}
log.PlcLog(String.Format("通过PLC地址{0}写入Double类型数据{1}失败!!!", address, value));
return false;
}
catch (Exception ex)
{
log.Error(String.Format("通过PLC地址{0}写入Double类型数据异常", address), ex);
return false;
}
}
}
}

@ -0,0 +1,107 @@
using HighWayIot.Log4net;
using HighWayIot.Plc.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HighWayIot.Plc
{
public sealed class PlcPool
{
private static readonly Lazy<PlcPool> lazy = new Lazy<PlcPool>(() => new PlcPool());
public static PlcPool Instance
{
get
{
return lazy.Value;
}
}
private LogHelper logHelper = LogHelper.Instance;
private Dictionary<string, IPlc> keyValuePairs = new Dictionary<string, IPlc>();
private PlcPool() { }
/// <summary>
/// 初始化Plc
/// </summary>
/// <param name="plcType"></param>
/// <param name="ip"></param>
/// <param name="port"></param>
/// <param name="key"></param>
public void InitPlc(string plcType,string ip,int port,string key)
{
IPlc _plc = null;
switch(plcType)
{
case "InovancePlc":
_plc = new InovancePlc();
break;
case "MelsecBinaryPlc":
_plc = new MelsecBinaryPlc();
break;
case "OmronNJPlc":
_plc = new OmronNJPlc();
break;
case "SiemensPlc":
_plc = new SiemensPlc();
break;
default:
break;
}
var connectResult = _plc.Connect(ip, port);
if (connectResult)
{
keyValuePairs.Add(key, _plc);
}
}
/// <summary>
/// 获取PLC
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public IPlc GetPlcByKey(string key)
{
return keyValuePairs[key];
}
/// <summary>
/// 获取所有PLC信息
/// </summary>
/// <returns></returns>
public Dictionary<string,IPlc> GetAll()
{
return keyValuePairs;
}
/// <summary>
/// 关闭所有连接
/// </summary>
/// <returns></returns>
public bool disConnectAll()
{
bool result = false;
try
{
foreach (var kv in keyValuePairs)
{
if (kv.Value != null)
{
kv.Value.DisConnect();
}
}
result = true;
}
catch(Exception ex)
{
logHelper.Error("关闭PLC连接异常", ex);
}
return result;
}
}
}

@ -1 +1 @@
887f1b5161fe575aee2d999ec37f9cca0db15a25
f80abeff4f54f6d92641a5ca021a378fc773b991

@ -150,7 +150,7 @@ namespace HighWayIot.Repository.service.Impl
RealTaskInfo taskInfo = null;
try
{
taskInfo = _mesRepository.GetFirst(x => string.IsNullOrEmpty(storeCode) ? 1==1 : x.storeCode == storeCode && x.taskCode == taskCode);
taskInfo = _mesRepository.GetFirst(x => x.storeCode == storeCode && x.taskCode == taskCode);
}
catch (Exception ex)
{

Loading…
Cancel
Save