using Admin.NET.Core.Service;
|
using DocumentFormat.OpenXml.Office2010.ExcelAc;
|
using Furion.InstantMessaging;
|
using Microsoft.AspNetCore.SignalR;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
|
namespace WCS.Application;
|
|
/// <summary>
|
/// 任务日志集线器
|
/// </summary>
|
[MapHub("/hubs/PlcDevice")]
|
public class PlcDeviceHub : Hub<IPlcDeviceHub>
|
{
|
private static readonly SysCacheService _sysCacheService = App.GetRequiredService<SysCacheService>();
|
private static bool boRunningState = false;
|
private static CancellationTokenSource cts;//取消线程标识
|
private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
|
public PlcDeviceHub()
|
{
|
}
|
|
/// <summary>
|
/// 连接
|
/// </summary>
|
/// <returns></returns>
|
public override async Task OnConnectedAsync()
|
{
|
var httpContext = Context.GetHttpContext();
|
var userId = (httpContext.User.FindFirst(ClaimConst.UserId)?.Value).ToLong();
|
_sysCacheService.Set("PlcDeviceHub:" + Context.ConnectionId, userId);
|
if (!boRunningState)
|
{
|
//开启读取服务线程
|
boRunningState = true;
|
cts = new CancellationTokenSource();//取消线程标识
|
//StartRead();
|
}
|
await base.OnConnectedAsync();
|
}
|
|
/// <summary>
|
/// 断开
|
/// </summary>
|
/// <param name="exception"></param>
|
/// <returns></returns>
|
public override async Task OnDisconnectedAsync(Exception exception)
|
{
|
_sysCacheService.Remove("PlcDeviceHub:" + Context.ConnectionId);
|
//如果没有连接了 就关闭线程不读了
|
if (_sysCacheService.GetKeysByPrefixKey("PlcDeviceHub").Count == 0)
|
{
|
cts.Cancel();
|
boRunningState = false;
|
}
|
await base.OnDisconnectedAsync(exception);
|
}
|
|
/// <summary>
|
/// 开启读取plc线程
|
/// </summary>
|
public static void StartRead()
|
{
|
Task.Run(() =>
|
{
|
// 用于保存每个设备的初始状态
|
var initialStates = new Dictionary<long, WcsDeviceOutput>();
|
|
var listPlc = _db.Queryable<WcsPlc>().Where(s => s.Type == PLCTypeEnum.StackingMachine || s.Type == PLCTypeEnum.ConveyorLine).Where(s => s.Enable == YesNoEnum.Y).ToList();
|
var listPlcId = listPlc.Select(s => s.Id).ToList();
|
var listPlcDevice = _db.Queryable<WcsDevice>().Where(s => s.DeviceType == DeviceTypeEnum.Business && listPlcId.Contains(s.PlcId)).Select<WcsDeviceOutput>().ToList();
|
var listPlcDeviceId = listPlcDevice.Select(s => s.Id).ToList();
|
var listPlcStation = _db.Queryable<WcsPosition>().Where(s => listPlcDeviceId.Contains(s.DeviceId)).ToList();
|
while (true)
|
{
|
try
|
{
|
//获取跺机的状态
|
foreach (var modDevice in listPlcDevice)
|
{
|
//取消线程
|
if (cts.Token.IsCancellationRequested)
|
{
|
throw new OperationCanceledException();
|
}
|
var modPlc = listPlc.Where(s => s.Id == modDevice.PlcId).FirstOrDefault();
|
modDevice.Type = modPlc.Type;
|
//读取plc的值
|
var modConn = PLCTaskAction.listPlcConn.FirstOrDefault(s => s != null && s.PlcId == modDevice.PlcId);
|
if (modConn == null)
|
{
|
modDevice.Status = false;
|
continue;
|
}
|
else
|
{
|
modDevice.Status = modConn.Connected;
|
}
|
if (modConn.Connected)
|
{
|
var listPosition = listPlcStation.Where(s => s.DeviceId == modDevice.Id).ToList();
|
(var result, var plc) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos);
|
modDevice.Plc = Convert.ToString(plc);
|
(result, var wcs) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
|
modDevice.Wcs = Convert.ToString(wcs);
|
//任务号
|
var modPositionTask = listPosition.FirstOrDefault(s => s.Text == "任务号");
|
if (modPositionTask != null)
|
{
|
(result, var taskNo) = modConn.GetPlcDBValue(modPositionTask.PosType, modDevice.DbNumber, modPositionTask.PlcPos, modPositionTask.StringLength);
|
modDevice.TaskNo = Convert.ToString(taskNo);
|
}
|
//任务类型
|
var modPositionTaskType = listPosition.FirstOrDefault(s => s.Text == "任务类型");
|
if (modPositionTaskType != null)
|
{
|
(result, var taskType) = modConn.GetPlcDBValue(modPositionTaskType.PosType, modDevice.DbNumber, modPositionTaskType.PlcPos);
|
modDevice.TaskType = (TaskTypeEnum)Convert.ToInt32(taskType);
|
}
|
//起始工位
|
var modPositionStartLocatNo = listPosition.FirstOrDefault(s => s.Text == "起始工位");
|
if (modPositionStartLocatNo != null)
|
{
|
(result, var startLocatNo) = modConn.GetPlcDBValue(modPositionStartLocatNo.PosType, modDevice.DbNumber, modPositionStartLocatNo.PlcPos);
|
modDevice.StartLocatNo = Convert.ToString(startLocatNo);
|
}
|
//目的工位
|
var modPositionEndLocatNo = listPosition.FirstOrDefault(s => s.Text == "目的工位");
|
if (modPositionEndLocatNo != null)
|
{
|
(result, var endLocatNo) = modConn.GetPlcDBValue(modPositionEndLocatNo.PosType, modDevice.DbNumber, modPositionEndLocatNo.PlcPos);
|
modDevice.EndLocatNo = Convert.ToString(endLocatNo);
|
}
|
//托盘码
|
var modPositionPalletNo = listPosition.FirstOrDefault(s => s.Text == "托盘码");
|
if (modPositionPalletNo != null)
|
{
|
(result, var palletNo) = modConn.GetPlcDBValue(modPositionPalletNo.PosType, modDevice.DbNumber, modPositionPalletNo.PlcPos, modPositionPalletNo.StringLength);
|
modDevice.PalletNo = Convert.ToString(palletNo);
|
}
|
if (modPlc.Type == PLCTypeEnum.ConveyorLine)
|
{
|
//放货排
|
var modPositionReleaseRow = listPosition.FirstOrDefault(s => s.Text == "放货排");
|
if (modPositionReleaseRow != null)
|
{
|
(result, var releaseRow) = modConn.GetPlcDBValue(modPositionReleaseRow.PosType, modDevice.DbNumber, modPositionReleaseRow.PlcPos);
|
modDevice.ReleaseRow = Convert.ToInt32(releaseRow);
|
}
|
//放货列
|
var modPositionReleaseCol = listPosition.FirstOrDefault(s => s.Text == "放货列");
|
if (modPositionReleaseCol != null)
|
{
|
(result, var releaseCol) = modConn.GetPlcDBValue(modPositionReleaseCol.PosType, modDevice.DbNumber, modPositionReleaseCol.PlcPos);
|
modDevice.ReleaseCol = Convert.ToInt32(releaseCol);
|
}
|
//放货层
|
var modPositionReleaseStorey = listPosition.FirstOrDefault(s => s.Text == "放货层");
|
if (modPositionReleaseStorey != null)
|
{
|
(result, var releaseStorey) = modConn.GetPlcDBValue(modPositionReleaseStorey.PosType, modDevice.DbNumber, modPositionReleaseStorey.PlcPos);
|
modDevice.ReleaseStorey = Convert.ToInt32(releaseStorey);
|
}
|
//取货排
|
var modPositionPickRow = listPosition.FirstOrDefault(s => s.Text == "取货排");
|
if (modPositionPickRow != null)
|
{
|
(result, var pickRow) = modConn.GetPlcDBValue(modPositionPickRow.PosType, modDevice.DbNumber, modPositionPickRow.PlcPos);
|
modDevice.PickRow = Convert.ToInt32(pickRow);
|
}
|
//取货列
|
var modPositionPickCol = listPosition.FirstOrDefault(s => s.Text == "取货列");
|
if (modPositionPickCol != null)
|
{
|
(result, var pickCol) = modConn.GetPlcDBValue(modPositionPickCol.PosType, modDevice.DbNumber, modPositionPickCol.PlcPos);
|
modDevice.PickCol = Convert.ToInt32(pickCol);
|
}
|
//取货层
|
var modPositionPickStorey = listPosition.FirstOrDefault(s => s.Text == "取货层");
|
if (modPositionPickStorey != null)
|
{
|
(result, var pickStorey) = modConn.GetPlcDBValue(modPositionPickStorey.PosType, modDevice.DbNumber, modPositionPickStorey.PlcPos);
|
modDevice.PickStorey = Convert.ToInt32(pickStorey);
|
}
|
|
if (modPlc.Type == PLCTypeEnum.StackingMachine)
|
{
|
//跺机的起始工位用取货排列层
|
modDevice.StartLocatNo = $"{modDevice.PickRow.ToString()}{modDevice.PickCol.ToString()}{modDevice.PickStorey.ToString()}";
|
//跺机的目的工位用放货排列层
|
modDevice.EndLocatNo = $"{modDevice.ReleaseRow.ToString()}{modDevice.ReleaseCol.ToString()}{modDevice.ReleaseStorey.ToString()}";
|
}
|
}
|
}
|
//else
|
//{
|
// //测试
|
// modDevice.TaskNo = "TK00001";
|
// modDevice.TaskType = TaskTypeEnum.In;
|
// modDevice.Wcs = new Random().Next(1000).ToString();
|
// modDevice.Plc = new Random().Next(1000).ToString();
|
// modDevice.Status = true;
|
//}
|
// 比较之前的状态
|
if (initialStates.TryGetValue(modDevice.Id, out var initialState))
|
{
|
if (modDevice.Status != initialState.Status ||
|
(modDevice.Plc.IsNullOrEmpty() && modDevice.Plc != initialState.Plc) ||
|
modDevice.Wcs != initialState.Wcs ||
|
modDevice.TaskNo != initialState.TaskNo ||
|
modDevice.TaskType != initialState.TaskType ||
|
modDevice.StartLocatNo != initialState.StartLocatNo ||
|
modDevice.EndLocatNo != initialState.EndLocatNo ||
|
modDevice.PalletNo != initialState.PalletNo ||
|
(modPlc.Type == PLCTypeEnum.ConveyorLine &&
|
(modDevice.ReleaseRow != initialState.ReleaseRow ||
|
modDevice.ReleaseCol != initialState.ReleaseCol ||
|
modDevice.ReleaseStorey != initialState.ReleaseStorey ||
|
modDevice.PickRow != initialState.PickRow ||
|
modDevice.PickCol != initialState.PickCol ||
|
modDevice.PickStorey != initialState.PickStorey)))
|
{
|
// 通知用户变更
|
//HubUtil.PublicPlcDevice(modDevice);
|
}
|
}
|
initialStates[modDevice.Id] = modDevice.Adapt<WcsDeviceOutput>();
|
}
|
Thread.Sleep(2000);
|
}
|
catch (OperationCanceledException)
|
{
|
break;
|
}
|
catch (Exception)
|
{
|
|
}
|
}
|
}, cts.Token);
|
}
|
}
|