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;
///
/// 任务日志集线器
///
[MapHub("/hubs/PlcDevice")]
public class PlcDeviceHub : Hub
{
private static readonly SysCacheService _sysCacheService = App.GetRequiredService();
private static bool boRunningState = false;
private static CancellationTokenSource cts;//取消线程标识
private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
public PlcDeviceHub()
{
}
///
/// 连接
///
///
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();
}
///
/// 断开
///
///
///
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);
}
///
/// 开启读取plc线程
///
public static void StartRead()
{
Task.Run(() =>
{
// 用于保存每个设备的初始状态
var initialStates = new Dictionary();
var listPlc = _db.Queryable().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().Where(s => s.DeviceType == DeviceTypeEnum.Business && listPlcId.Contains(s.PlcId)).Select().ToList();
var listPlcDeviceId = listPlcDevice.Select(s => s.Id).ToList();
var listPlcStation = _db.Queryable().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();
}
Thread.Sleep(2000);
}
catch (OperationCanceledException)
{
break;
}
catch (Exception)
{
}
}
}, cts.Token);
}
}