修改
This commit is contained in:
102
DOAN.Admin.WebApi/Controllers/PBL/Logging/AlarmLogController.cs
Normal file
102
DOAN.Admin.WebApi/Controllers/PBL/Logging/AlarmLogController.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using DOAN.Model.PBL.Dto;
|
||||
using DOAN.Model.PBL;
|
||||
using DOAN.Service.PBL.IPBLService;
|
||||
using DOAN.Admin.WebApi.Filters;
|
||||
|
||||
//创建时间:2025-02-22
|
||||
namespace DOAN.Admin.WebApi.Controllers.PBL
|
||||
{
|
||||
/// <summary>
|
||||
/// 库存报警日志
|
||||
/// </summary>
|
||||
[Verify]
|
||||
[Route("PBL/AlarmLog")]
|
||||
public class AlarmLogController : BaseController
|
||||
{
|
||||
/// <summary>
|
||||
/// 库存报警日志接口
|
||||
/// </summary>
|
||||
private readonly IAlarmLogService _AlarmLogService;
|
||||
|
||||
public AlarmLogController(IAlarmLogService AlarmLogService)
|
||||
{
|
||||
_AlarmLogService = AlarmLogService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询库存报警日志列表
|
||||
/// </summary>
|
||||
/// <param name="parm"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("list")]
|
||||
[ActionPermissionFilter(Permission = "alarmlog:list")]
|
||||
public IActionResult QueryAlarmLog([FromQuery] AlarmLogQueryDto parm)
|
||||
{
|
||||
var response = _AlarmLogService.GetList(parm);
|
||||
return SUCCESS(response);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 查询库存报警日志详情
|
||||
/// </summary>
|
||||
/// <param name="Id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{Id}")]
|
||||
[ActionPermissionFilter(Permission = "alarmlog:query")]
|
||||
public IActionResult GetAlarmLog(string Id)
|
||||
{
|
||||
var response = _AlarmLogService.GetInfo(Id);
|
||||
|
||||
var info = response.Adapt<AlarmLogDto>();
|
||||
return SUCCESS(info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加库存报警日志
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[ActionPermissionFilter(Permission = "alarmlog:add")]
|
||||
[Log(Title = "库存报警日志", BusinessType = BusinessType.INSERT)]
|
||||
public IActionResult AddAlarmLog([FromBody] AlarmLogDto parm)
|
||||
{
|
||||
var modal = parm.Adapt<AlarmLog>().ToCreate(HttpContext);
|
||||
|
||||
var response = _AlarmLogService.AddAlarmLog(modal);
|
||||
|
||||
return SUCCESS(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新库存报警日志
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPut]
|
||||
[ActionPermissionFilter(Permission = "alarmlog:edit")]
|
||||
[Log(Title = "库存报警日志", BusinessType = BusinessType.UPDATE)]
|
||||
public IActionResult UpdateAlarmLog([FromBody] AlarmLogDto parm)
|
||||
{
|
||||
var modal = parm.Adapt<AlarmLog>().ToUpdate(HttpContext);
|
||||
var response = _AlarmLogService.UpdateAlarmLog(modal);
|
||||
|
||||
return ToResponse(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除库存报警日志
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("delete/{ids}")]
|
||||
[ActionPermissionFilter(Permission = "alarmlog:delete")]
|
||||
[Log(Title = "库存报警日志", BusinessType = BusinessType.DELETE)]
|
||||
public IActionResult DeleteAlarmLog([FromRoute]string ids)
|
||||
{
|
||||
var idArr = Tools.SplitAndConvert<string>(ids);
|
||||
|
||||
return ToResponse(_AlarmLogService.Delete(idArr));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
60
DOAN.Model/PBL/AlarmLog.cs
Normal file
60
DOAN.Model/PBL/AlarmLog.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
namespace DOAN.Model.PBL
|
||||
{
|
||||
/// <summary>
|
||||
/// 库存报警日志
|
||||
/// </summary>
|
||||
[SugarTable("alarm_log")]
|
||||
public class AlarmLog
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = false)]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 料架id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "storagelocation_id")]
|
||||
public int? StoragelocationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统类别
|
||||
/// </summary>
|
||||
public int? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统状态
|
||||
/// </summary>
|
||||
public int? Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发生时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "action_time")]
|
||||
public DateTime? ActionTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 完成报警时间
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "end_time")]
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
48
DOAN.Model/PBL/Dto/AlarmLogDto.cs
Normal file
48
DOAN.Model/PBL/Dto/AlarmLogDto.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
namespace DOAN.Model.PBL.Dto
|
||||
{
|
||||
/// <summary>
|
||||
/// 库存报警日志查询对象
|
||||
/// </summary>
|
||||
public class AlarmLogQueryDto : PagerInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Code { get; set; }
|
||||
public int? StoragelocationId { get; set; }
|
||||
public int? Type { get; set; }
|
||||
public int? Status { get; set; }
|
||||
|
||||
public DateTime? StartTime { get; set; }
|
||||
public DateTime? EndTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 库存报警日志输入输出对象
|
||||
/// </summary>
|
||||
public class AlarmLogDto
|
||||
{
|
||||
[Required(ErrorMessage = "主键不能为空")]
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Code { get; set; }
|
||||
|
||||
public int? StoragelocationId { get; set; }
|
||||
|
||||
public int? Type { get; set; }
|
||||
|
||||
public int? Status { get; set; }
|
||||
|
||||
public string Remark { get; set; }
|
||||
|
||||
public DateTime? ActionTime { get; set; }
|
||||
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
||||
|
||||
|
||||
[ExcelColumn(Name = "系统类别")]
|
||||
public string TypeLabel { get; set; }
|
||||
}
|
||||
}
|
||||
48
DOAN.Model/PBL/PlcButton.cs
Normal file
48
DOAN.Model/PBL/PlcButton.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DOAN.Model.PBL
|
||||
{
|
||||
/// <summary>
|
||||
/// PLC地址
|
||||
/// </summary>
|
||||
[SugarTable("plc_button_table")]
|
||||
public class PlcButton
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = false)]
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 按钮名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 按钮型号
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 料架id
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnName = "storagelocation_id")]
|
||||
public int StoragelocationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// PLC地址
|
||||
/// </summary>
|
||||
public int Address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// PLC地址下标
|
||||
/// </summary>
|
||||
public int Index { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
87
DOAN.Service/PBL/AlarmLogService.cs
Normal file
87
DOAN.Service/PBL/AlarmLogService.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using Infrastructure.Attribute;
|
||||
using Infrastructure.Extensions;
|
||||
using DOAN.Model.PBL.Dto;
|
||||
using DOAN.Model.PBL;
|
||||
using DOAN.Repository;
|
||||
using DOAN.Service.PBL.IPBLService;
|
||||
|
||||
namespace DOAN.Service.PBL
|
||||
{
|
||||
/// <summary>
|
||||
/// 库存报警日志Service业务层处理
|
||||
/// </summary>
|
||||
[AppService(ServiceType = typeof(IAlarmLogService), ServiceLifetime = LifeTime.Transient)]
|
||||
public class AlarmLogService : BaseService<AlarmLog>, IAlarmLogService
|
||||
{
|
||||
/// <summary>
|
||||
/// 查询库存报警日志列表
|
||||
/// </summary>
|
||||
/// <param name="parm"></param>
|
||||
/// <returns></returns>
|
||||
public PagedInfo<AlarmLogDto> GetList(AlarmLogQueryDto parm)
|
||||
{
|
||||
var predicate = QueryExp(parm);
|
||||
|
||||
var response = Queryable()
|
||||
.Where(predicate.ToExpression())
|
||||
.ToPage<AlarmLog, AlarmLogDto>(parm);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取详情
|
||||
/// </summary>
|
||||
/// <param name="Id"></param>
|
||||
/// <returns></returns>
|
||||
public AlarmLog GetInfo(string Id)
|
||||
{
|
||||
var response = Queryable()
|
||||
.Where(x => x.Id == Id)
|
||||
.First();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加库存报警日志
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
public AlarmLog AddAlarmLog(AlarmLog model)
|
||||
{
|
||||
return Insertable(model).ExecuteReturnEntity();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改库存报警日志
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
public int UpdateAlarmLog(AlarmLog model)
|
||||
{
|
||||
return Update(model, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询导出表达式
|
||||
/// </summary>
|
||||
/// <param name="parm"></param>
|
||||
/// <returns></returns>
|
||||
private static Expressionable<AlarmLog> QueryExp(AlarmLogQueryDto parm)
|
||||
{
|
||||
var predicate = Expressionable.Create<AlarmLog>()
|
||||
.AndIF(!string.IsNullOrEmpty(parm.Name),it =>it.Name.Contains(parm.Name))
|
||||
.AndIF(!string.IsNullOrEmpty(parm.Code), it => it.Code.Contains(parm.Code))
|
||||
.AndIF(parm.Type > -1, it => it.Type == parm.Type)
|
||||
.AndIF(parm.Status > -1, it => it.Status == parm.Status)
|
||||
.AndIF(parm.StoragelocationId > -1, it => it.StoragelocationId == parm.StoragelocationId)
|
||||
.AndIF(parm.StartTime.HasValue, it => it.ActionTime >= parm.StartTime)
|
||||
.AndIF(parm.EndTime.HasValue, it => it.ActionTime <= parm.EndTime)
|
||||
;
|
||||
|
||||
return predicate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,7 +142,8 @@ public class BigScreenService : BaseService<Storagelocation>, IBigScreenService
|
||||
AlarmNum = layer.AlarmNum ?? 2, // 确认默认值
|
||||
PackageNum = layer.PackageNum ?? 0,
|
||||
IsLight = layer.IsLight == 1,
|
||||
IsFeedingMaterial = (layer.PackageNum ?? 0) <= (layer.AlarmNum ?? 2) && layer.IsLackAlarm == 1
|
||||
// IsFeedingMaterial = (layer.PackageNum ?? 0) < (layer.AlarmNum ?? 2) && layer.IsLackAlarm == 1
|
||||
IsFeedingMaterial = CalculateIsOneLayerNumFeedingMaterial(layer)
|
||||
}).ToArray();
|
||||
var rackDto = new BigScreenDto
|
||||
{
|
||||
@@ -150,7 +151,8 @@ public class BigScreenService : BaseService<Storagelocation>, IBigScreenService
|
||||
RackCode = group.Key,
|
||||
IsLight = layers.Any(l => l.IsLight == 1),
|
||||
IsInUse = layers.Any(l => l.IsLackAlarm == 1),
|
||||
IsFeedingMaterial = layers.Any(l => (l.PackageNum ?? 0) <= (l.AlarmNum ?? 2) && l.IsLackAlarm == 1),
|
||||
// IsFeedingMaterial = layers.Any(l => (l.PackageNum ?? 0) < (l.AlarmNum ?? 2) && l.IsLackAlarm == 1),
|
||||
IsFeedingMaterial = CalculateIsAllFeedingMaterial(layers),
|
||||
LayerObjectArray = layerObjects
|
||||
};
|
||||
result.Add(rackDto);
|
||||
@@ -158,4 +160,40 @@ public class BigScreenService : BaseService<Storagelocation>, IBigScreenService
|
||||
|
||||
return result;
|
||||
}
|
||||
// 将复杂逻辑封装到方法中
|
||||
private bool CalculateIsAllFeedingMaterial(List<Storagelocation> layers)
|
||||
{
|
||||
int OneTotalPackageNum = layers.Where(it => it.LayerNum == 1).Sum(it => it.PackageNum ?? 0);
|
||||
int SecondTotalPackageNum = layers.Where(it => it.LayerNum == 2).Sum(it => it.PackageNum ?? 0);
|
||||
int alarmNum = 2;
|
||||
if (layers.Any(ls => ls.Remark == "合并料架"))
|
||||
{
|
||||
alarmNum = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
alarmNum = layers[0].AlarmNum ?? 0;
|
||||
}
|
||||
return OneTotalPackageNum < alarmNum || SecondTotalPackageNum < alarmNum;
|
||||
|
||||
}
|
||||
|
||||
private bool CalculateIsOneLayerNumFeedingMaterial(Storagelocation layer)
|
||||
{
|
||||
if (layer.Remark == "合并料架")
|
||||
{
|
||||
int totalPackageNum = Context.Queryable<Storagelocation>()
|
||||
.Where(it => it.LayerNum == layer.LayerNum)
|
||||
.Where(it => it.RackCode == layer.RackCode)
|
||||
.Sum(it => it.PackageNum ?? 0);
|
||||
return totalPackageNum < 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (layer.PackageNum ?? 0) < (layer.AlarmNum ?? 2) && layer.IsLackAlarm == 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
21
DOAN.Service/PBL/IService/IAlarmLogService.cs
Normal file
21
DOAN.Service/PBL/IService/IAlarmLogService.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using DOAN.Model.PBL.Dto;
|
||||
using DOAN.Model.PBL;
|
||||
|
||||
namespace DOAN.Service.PBL.IPBLService
|
||||
{
|
||||
/// <summary>
|
||||
/// 库存报警日志service接口
|
||||
/// </summary>
|
||||
public interface IAlarmLogService : IBaseService<AlarmLog>
|
||||
{
|
||||
PagedInfo<AlarmLogDto> GetList(AlarmLogQueryDto parm);
|
||||
|
||||
AlarmLog GetInfo(string Id);
|
||||
|
||||
|
||||
AlarmLog AddAlarmLog(AlarmLog parm);
|
||||
int UpdateAlarmLog(AlarmLog parm);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,9 @@ using Mapster;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using static System.Formats.Asn1.AsnWriter;
|
||||
|
||||
namespace DOAN.Service.PBL
|
||||
{
|
||||
@@ -39,77 +41,154 @@ namespace DOAN.Service.PBL
|
||||
/// <returns></returns>
|
||||
public bool MESLightUp(LightUpDto light, PLCTool pLCTool)
|
||||
{
|
||||
int result = 0;
|
||||
// 1.记录MES交互记录
|
||||
MES_Interation_Log item = light.Adapt<MES_Interation_Log>();
|
||||
item.Id = XUEHUA;
|
||||
item.CreatedTime = DateTime.Now;
|
||||
Context.Insertable(item).ExecuteCommand();
|
||||
// 2.根据总成零件号 ,版本 查询对应零件号,使得对应料架亮灯
|
||||
List<Storagelocation> MirrorshellShelfList = Context
|
||||
.Queryable<Storagelocation>()
|
||||
.Where(it =>
|
||||
it.Partnumber
|
||||
== SqlFunc
|
||||
.Subqueryable<Billofmaterials>()
|
||||
.Where(It => It.Productcode == light.AssemblyPartNumber)
|
||||
.Select(it => it.MirrorshellCode)
|
||||
)
|
||||
.ToList();
|
||||
if (MirrorshellShelfList != null && MirrorshellShelfList.Count() > 0)
|
||||
try
|
||||
{
|
||||
Storagelocation storagelocation = new();
|
||||
// 是否合并料架
|
||||
bool isMergeRack = MirrorshellShelfList.Count > 1;
|
||||
if (isMergeRack)
|
||||
Context.Ado.BeginTran();
|
||||
int result = 0;
|
||||
// 1.记录MES交互记录
|
||||
MES_Interation_Log item = light.Adapt<MES_Interation_Log>();
|
||||
item.Id = XUEHUA;
|
||||
item.CreatedTime = DateTime.Now;
|
||||
Context.Insertable(item).ExecuteCommand();
|
||||
// 2.根据总成零件号 ,版本 查询对应零件号,使得对应料架亮灯
|
||||
List<Storagelocation> MirrorshellShelfList = Context
|
||||
.Queryable<Storagelocation>()
|
||||
.Where(it =>
|
||||
it.Partnumber
|
||||
== SqlFunc
|
||||
.Subqueryable<Billofmaterials>()
|
||||
.Where(It => It.Productcode == light.AssemblyPartNumber)
|
||||
.Select(it => it.MirrorshellCode)
|
||||
)
|
||||
.ToList();
|
||||
if (MirrorshellShelfList != null && MirrorshellShelfList.Count() > 0)
|
||||
{
|
||||
// 合并料架 判断先进先出
|
||||
foreach(var shelf in MirrorshellShelfList)
|
||||
Storagelocation storagelocation = new();
|
||||
// 是否合并料架
|
||||
bool isMergeRack = MirrorshellShelfList.Count > 1;
|
||||
if (isMergeRack)
|
||||
{
|
||||
// 第一个有箱子的
|
||||
if(shelf.PackageNum > 0)
|
||||
Storagelocation leftShelf = MirrorshellShelfList[0];
|
||||
Storagelocation rightShelf = MirrorshellShelfList[1];
|
||||
// 料架今天是否有补料信息 (补料完成信号判定)
|
||||
var today = DateTime.Today;
|
||||
bool hasAlarm = Context.Queryable<AlarmLog>()
|
||||
.Where(it => it.ActionTime != null &&
|
||||
it.ActionTime >= today &&
|
||||
it.ActionTime < today.AddDays(1))
|
||||
.Where(it => it.StoragelocationId == leftShelf.Id || it.StoragelocationId == rightShelf.Id)
|
||||
.OrderByDescending(it => it.ActionTime)
|
||||
.Any();
|
||||
int packageTotal = leftShelf.PackageNum.Value + rightShelf.PackageNum.Value;
|
||||
//1. 在今日有补料信号的前提下 料架>6箱(已补料,未消耗最新箱,先消耗旧箱,哪边存在报警补哪边)
|
||||
if (packageTotal == 8 && hasAlarm)
|
||||
{
|
||||
storagelocation = shelf;
|
||||
continue;
|
||||
if (leftShelf.IsLackAlarm == 1)
|
||||
{
|
||||
storagelocation = leftShelf;
|
||||
}
|
||||
else if (rightShelf.IsLackAlarm == 1)
|
||||
{
|
||||
storagelocation = rightShelf;
|
||||
}
|
||||
else
|
||||
{
|
||||
storagelocation = rightShelf;
|
||||
}
|
||||
}
|
||||
else if (packageTotal == 7 && hasAlarm)
|
||||
{
|
||||
if (leftShelf.IsLackAlarm == 1)
|
||||
{
|
||||
storagelocation = leftShelf;
|
||||
}
|
||||
else if (rightShelf.IsLackAlarm == 1)
|
||||
{
|
||||
storagelocation = rightShelf;
|
||||
}
|
||||
else
|
||||
{
|
||||
storagelocation = rightShelf;
|
||||
}
|
||||
// 切换报警
|
||||
DoChangeAlarmStatus(leftShelf, rightShelf);
|
||||
}
|
||||
else if (packageTotal <= 6 && packageTotal > 4 && hasAlarm)
|
||||
{
|
||||
if (leftShelf.IsLackAlarm == 1)
|
||||
{
|
||||
storagelocation = rightShelf;
|
||||
}
|
||||
else if (rightShelf.IsLackAlarm == 1)
|
||||
{
|
||||
storagelocation = leftShelf;
|
||||
}
|
||||
else
|
||||
{
|
||||
storagelocation = rightShelf;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 默认情况
|
||||
// 合并料架 判断 20250224 左先出原则
|
||||
foreach (var shelf in MirrorshellShelfList)
|
||||
{
|
||||
// 第一个有箱子的料架
|
||||
if (shelf.PackageNum > 0)
|
||||
{
|
||||
storagelocation = shelf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (storagelocation.RackCode == null)
|
||||
{
|
||||
storagelocation = MirrorshellShelfList[^1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (storagelocation.RackCode == null)
|
||||
else
|
||||
{
|
||||
storagelocation = MirrorshellShelfList[^1];
|
||||
// 单独料架
|
||||
storagelocation = MirrorshellShelfList[0];
|
||||
}
|
||||
// 3.对应料架亮灯
|
||||
bool isSucesss = pLCTool.WriteBit(storagelocation.PlcAddress, true);
|
||||
if (isSucesss)
|
||||
{
|
||||
storagelocation.IsLight = 1;
|
||||
result += Context.Updateable(storagelocation).ExecuteCommand();
|
||||
}
|
||||
//亮灯日志
|
||||
Light_Log light_Log = new Light_Log();
|
||||
light_Log.Id = XUEHUA;
|
||||
light_Log.LightOperation = 1;
|
||||
light_Log.Operationer = "PBL";
|
||||
light_Log.CreatedTime = DateTime.Now;
|
||||
light_Log.ShelfCode = storagelocation.RackCode;
|
||||
light_Log.LayerNum = storagelocation.LayerNum;
|
||||
light_Log.IsSuccess = isSucesss;
|
||||
result += Context.Insertable(light_Log).ExecuteCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 单独料架
|
||||
storagelocation = MirrorshellShelfList[0];
|
||||
// 发送socket 通知
|
||||
string message =
|
||||
$"MES产品编号{light.AssemblyPartNumber}或者版本{light.Version},在PBL中找不到。请维护PBL料架信息--{DateTime.Now}";
|
||||
notificationHubContext.Clients.All.SendAsync("PBL_bom_except", message);
|
||||
Context.Ado.RollbackTran();
|
||||
return false;
|
||||
}
|
||||
// 3.对应料架亮灯
|
||||
bool isSucesss = pLCTool.WriteBit(storagelocation.PlcAddress, true);
|
||||
if (isSucesss) {
|
||||
storagelocation.IsLight = 1;
|
||||
result += Context.Updateable(storagelocation).ExecuteCommand();
|
||||
}
|
||||
//亮灯日志
|
||||
Light_Log light_Log = new Light_Log();
|
||||
light_Log.Id = XUEHUA;
|
||||
light_Log.LightOperation = 1;
|
||||
light_Log.Operationer = "PBL";
|
||||
light_Log.CreatedTime = DateTime.Now;
|
||||
light_Log.ShelfCode = storagelocation.RackCode;
|
||||
light_Log.LayerNum = storagelocation.LayerNum;
|
||||
light_Log.IsSuccess = isSucesss;
|
||||
result += Context.Insertable(light_Log).ExecuteCommand();
|
||||
notificationHubContext.Clients.All.SendAsync("PBL_storagelocation_change");
|
||||
Context.Ado.CommitTran();
|
||||
return result > 0;
|
||||
}
|
||||
else
|
||||
catch (Exception)
|
||||
{
|
||||
// 发送socket 通知
|
||||
string message =
|
||||
$"MES产品编号{light.AssemblyPartNumber}或者版本{light.Version},在PBL中找不到。请维护PBL料架信息--{DateTime.Now}";
|
||||
notificationHubContext.Clients.All.SendAsync("PBL_bom_except", message);
|
||||
|
||||
Context.Ado.RollbackTran();
|
||||
return false;
|
||||
}
|
||||
return result > 0;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -159,7 +238,27 @@ namespace DOAN.Service.PBL
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
result += Context.Insertable(light_Log).ExecuteCommand();
|
||||
notificationHubContext.Clients.All.SendAsync("PBL_storagelocation_change");
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 交换合并料架报警配置
|
||||
/// </summary>
|
||||
/// <param name="leftShelf"></param>
|
||||
/// <param name="rightShelf"></param>
|
||||
/// <returns></returns>
|
||||
public int DoChangeAlarmStatus(Storagelocation leftShelf, Storagelocation rightShelf)
|
||||
{
|
||||
int result = 0;
|
||||
// 都判断完后切换报警
|
||||
leftShelf.IsLackAlarm = leftShelf.IsLackAlarm == 1 ? 0 : 1;
|
||||
leftShelf.AlarmNum = leftShelf.IsLackAlarm == 1 ? rightShelf.AlarmNum : 0;
|
||||
result += Context.Updateable(leftShelf).ExecuteCommand();
|
||||
rightShelf.IsLackAlarm = rightShelf.IsLackAlarm == 1 ? 0 : 1;
|
||||
rightShelf.AlarmNum = rightShelf.IsLackAlarm == 1 ? leftShelf.AlarmNum : 0;
|
||||
result += Context.Updateable(rightShelf).ExecuteCommand();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using DOAN.Infrastructure.PLC;
|
||||
using DOAN.Model.PBL;
|
||||
using DOAN.ServiceCore.Signalr;
|
||||
using JinianNet.JNTemplate;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using SqlSugar.IOC;
|
||||
using static System.Formats.Asn1.AsnWriter;
|
||||
|
||||
namespace DOAN.ServiceCore
|
||||
{
|
||||
@@ -25,6 +29,7 @@ namespace DOAN.ServiceCore
|
||||
private PLCTool pLCTool;
|
||||
private List<Storagelocation> storagelocationList = new List<Storagelocation>();
|
||||
private List<PlcAddressTable> pointPositionList = new List<PlcAddressTable>();
|
||||
private List<PlcButton> buttonPositionList = new List<PlcButton>();
|
||||
private Timer refreshTimer;
|
||||
|
||||
public DoanBackgroundService(IHubContext<PBLhub> hubContext)
|
||||
@@ -34,17 +39,18 @@ namespace DOAN.ServiceCore
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
Console.WriteLine($"PCL定时任务开启!");
|
||||
pLCTool = new PLCTool();
|
||||
pLCTool.ConnectPLC();
|
||||
|
||||
// 初始化料架层和点位表数据
|
||||
RefreshData(null);
|
||||
|
||||
// 启动后台任务
|
||||
_executingTask = ExecuteAsync(_cancellationTokenSource.Token);
|
||||
|
||||
// 设置定时器每分钟刷新一次料架层和点位表
|
||||
refreshTimer = new Timer(RefreshData, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
|
||||
// 设置定时器每10分钟刷新一次料架层和点位表 .FromMinutes(1)
|
||||
refreshTimer = new Timer(RefreshData, null, TimeSpan.Zero, TimeSpan.FromMinutes(10));
|
||||
|
||||
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
|
||||
}
|
||||
@@ -66,7 +72,7 @@ namespace DOAN.ServiceCore
|
||||
{
|
||||
if (position < 0 || position > 7)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(position), "Position must be between 0 and 7.");
|
||||
throw new ArgumentOutOfRangeException(nameof(position), "Position must be between 0 and 7" + position);
|
||||
}
|
||||
|
||||
byte mask = (byte)(1 << position);
|
||||
@@ -81,6 +87,7 @@ namespace DOAN.ServiceCore
|
||||
/// <returns></returns>
|
||||
private async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
Console.WriteLine($"PCL定时任务ExecuteAsync!");
|
||||
try
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
@@ -89,13 +96,97 @@ namespace DOAN.ServiceCore
|
||||
byte[] plcSensorValues;
|
||||
try
|
||||
{
|
||||
plcSensorValues = pLCTool.ReadAllValue("VB100", 12);
|
||||
// 读取1开头100,101。。。等全部地址数据
|
||||
|
||||
plcSensorValues = pLCTool.ReadAllValue("VB100", 13);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"读取PLC数据异常: {ex.Message}\n堆栈跟踪: {ex.StackTrace}");
|
||||
continue;
|
||||
}
|
||||
// XX 按钮处理
|
||||
|
||||
|
||||
// 读取按钮PLC I/O状态
|
||||
foreach (PlcButton button in buttonPositionList)
|
||||
{
|
||||
|
||||
int row = button.Address - 100;
|
||||
int col = button.Index;
|
||||
|
||||
if (plcSensorValues != null && row >= 0 && row < plcSensorValues.Length && !GetInvertedBit(plcSensorValues[row], col))
|
||||
{
|
||||
// 按钮按下灭灯
|
||||
if (button.Code == "灭灯按钮")
|
||||
{
|
||||
|
||||
Storagelocation offLightstoragelocation = storagelocationList.Where(it => it.Id == button.StoragelocationId).First();
|
||||
bool isSuccess = pLCTool.WriteBit(offLightstoragelocation.PlcAddress, false);
|
||||
if (isSuccess)
|
||||
{
|
||||
offLightstoragelocation.IsLight = 0;
|
||||
using (var scope = DbScoped.SugarScope.CopyNew())
|
||||
{
|
||||
await scope.Updateable(offLightstoragelocation).ExecuteCommandAsync();
|
||||
//灭灯日志
|
||||
Light_Log light_Log = new Light_Log
|
||||
{
|
||||
Id = SnowFlakeSingle.Instance.NextId().ToString(),
|
||||
LightOperation = 2,
|
||||
LayerNum = offLightstoragelocation.LayerNum,
|
||||
ShelfCode = offLightstoragelocation.RackCode,
|
||||
IsSuccess = isSuccess,
|
||||
Operationer = "按钮手动灭灯",
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
await scope.Insertable(light_Log).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
await notificationHubContext.Clients.All.SendAsync("PBL_storagelocation_change", "手动灭灯");
|
||||
}
|
||||
// 镜体补料按钮
|
||||
if (button.Code == "镜体补料按钮")
|
||||
{
|
||||
bool lightStatus = pLCTool.ReadBit("V208.4");
|
||||
// 原本灭灯,亮灯补料
|
||||
if (!lightStatus)
|
||||
{
|
||||
using (var scope = DbScoped.SugarScope.CopyNew())
|
||||
{
|
||||
AlarmLog alarmLog = new AlarmLog
|
||||
{
|
||||
Id = SnowFlakeSingle.Instance.NextId().ToString(),
|
||||
Name = "镜体需要补料",
|
||||
Code = "镜体补料",
|
||||
StoragelocationId = 0,
|
||||
Type = 2,
|
||||
Status = 1,
|
||||
ActionTime = DateTime.Now,
|
||||
EndTime = DateTime.Now
|
||||
};
|
||||
scope.Insertable(alarmLog).ExecuteCommand();
|
||||
var alarmData = new
|
||||
{
|
||||
RackCode = "镜体需要补料",
|
||||
LayerNum = 1,
|
||||
CurrentPackageCount = 0,
|
||||
AlarmThreshold = 1,
|
||||
ActionTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss").ToString(),
|
||||
};
|
||||
string alarmMessage = System.Text.Json.JsonSerializer.Serialize(alarmData);
|
||||
await notificationHubContext.Clients.All.SendAsync("PBL_lack_alarm", alarmMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 原本亮灯,按一下灭灯
|
||||
pLCTool.WriteBit("V208.4", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var updateStoragelocationList = new List<Storagelocation>();
|
||||
var inventoryLogs = new List<Inventorylog>();
|
||||
@@ -134,17 +225,46 @@ namespace DOAN.ServiceCore
|
||||
}
|
||||
|
||||
// 补料报警触发
|
||||
if (layerItem.IsLackAlarm == 1 && currentPackageCount <= layerItem.AlarmNum.GetValueOrDefault())
|
||||
if (layerItem.IsLackAlarm == 1 && currentPackageCount < layerItem.AlarmNum)
|
||||
{
|
||||
var alarmData = new
|
||||
using (var scope = DbScoped.SugarScope.CopyNew())
|
||||
{
|
||||
RackCode = layerItem.RackCode,
|
||||
LayerNum = layerItem.LayerNum,
|
||||
CurrentPackageCount = currentPackageCount,
|
||||
AlarmThreshold = layerItem.AlarmNum
|
||||
};
|
||||
string alarmMessage = System.Text.Json.JsonSerializer.Serialize(alarmData);
|
||||
await notificationHubContext.Clients.All.SendAsync("PBL_lack_alarm", alarmMessage);
|
||||
// 是否已经报警过,并且
|
||||
bool hasLastAlarm = await scope.Queryable<AlarmLog>()
|
||||
.Where(it => it.StoragelocationId == layerItem.Id)
|
||||
.Where(it => it.Type == 1)
|
||||
.Where(it => it.Status == 1)
|
||||
.Where(it => DateTime.Now <= it.EndTime)
|
||||
.OrderBy(it => it.ActionTime, OrderByType.Desc)
|
||||
.AnyAsync();
|
||||
if (!hasLastAlarm)
|
||||
{
|
||||
string layerName = layerItem.LayerNum == 1 ? "上层" : "中层";
|
||||
AlarmLog alarmLog = new AlarmLog
|
||||
{
|
||||
Id = SnowFlakeSingle.Instance.NextId().ToString(),
|
||||
Name = $"镜壳需补料:{layerItem.RackCode} {layerName} 阈值{layerItem.AlarmNum}",
|
||||
Code = "镜壳补料",
|
||||
StoragelocationId = layerItem.Id,
|
||||
Type = 1,
|
||||
Status = 1,
|
||||
ActionTime = DateTime.Now,
|
||||
// 过X分钟超时jishi
|
||||
EndTime = DateTime.Now.AddMinutes(2)
|
||||
};
|
||||
await scope.Insertable(alarmLog).ExecuteCommandAsync();
|
||||
var alarmData = new
|
||||
{
|
||||
RackCode = layerItem.RackCode,
|
||||
LayerNum = layerItem.LayerNum,
|
||||
CurrentPackageCount = currentPackageCount,
|
||||
AlarmThreshold = layerItem.AlarmNum,
|
||||
ActionTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss").ToString(),
|
||||
};
|
||||
string alarmMessage = System.Text.Json.JsonSerializer.Serialize(alarmData);
|
||||
await notificationHubContext.Clients.All.SendAsync("PBL_lack_alarm", alarmMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,7 +272,12 @@ namespace DOAN.ServiceCore
|
||||
// 更新库存
|
||||
if (updateStoragelocationList.Any())
|
||||
{
|
||||
await DbScoped.SugarScope.CopyNew().Updateable(updateStoragelocationList).ExecuteCommandAsync();
|
||||
using (var scope = DbScoped.SugarScope.CopyNew())
|
||||
{
|
||||
await scope.Updateable(updateStoragelocationList)
|
||||
.IgnoreColumns(it => new { it.IsLight, it.IsLackAlarm, it.AlarmNum, it.MaxCapacity })
|
||||
.ExecuteCommandAsync();
|
||||
}
|
||||
// 发送库存变更Socket通知
|
||||
string changeMessage = "库存变动";
|
||||
await notificationHubContext.Clients.All.SendAsync("PBL_storagelocation_change", changeMessage);
|
||||
@@ -163,8 +288,8 @@ namespace DOAN.ServiceCore
|
||||
{
|
||||
await DbScoped.SugarScope.CopyNew().Insertable(inventoryLogs).ExecuteCommandAsync();
|
||||
}
|
||||
// 添加延迟以避免频繁查询
|
||||
await Task.Delay(200, stoppingToken);
|
||||
// 添加延迟以避免频繁查询(暂定3秒防误触)
|
||||
await Task.Delay(2000, stoppingToken);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -181,14 +306,16 @@ namespace DOAN.ServiceCore
|
||||
/// 刷新料架层和点位表数据
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
private void RefreshData(object state)
|
||||
private async void RefreshData(object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"刷新料架点位和按钮");
|
||||
using (var scope = DbScoped.SugarScope.CopyNew())
|
||||
{
|
||||
storagelocationList = scope.Queryable<Storagelocation>().ToListAsync().Result;
|
||||
pointPositionList = scope.Queryable<PlcAddressTable>().ToListAsync().Result;
|
||||
storagelocationList = await scope.Queryable<Storagelocation>().ToListAsync();
|
||||
pointPositionList = await scope.Queryable<PlcAddressTable>().ToListAsync();
|
||||
buttonPositionList = await scope.Queryable<PlcButton>().ToListAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -235,12 +362,12 @@ namespace DOAN.ServiceCore
|
||||
{
|
||||
try
|
||||
{
|
||||
pLCTool.ConnectClose();
|
||||
_cancellationTokenSource.Cancel();
|
||||
_executingTask?.Wait();
|
||||
_executingTask?.GetAwaiter().GetResult(); // 确保任务完成
|
||||
_cancellationTokenSource.Dispose();
|
||||
refreshTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
refreshTimer?.Dispose();
|
||||
pLCTool.ConnectClose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user