164 lines
5.9 KiB
C#
164 lines
5.9 KiB
C#
using IoTClient.Clients.PLC;
|
|
using IoTClient.Common.Enums;
|
|
using LessokajiWeaverUtilities.Utilities;
|
|
using Newtonsoft.Json;
|
|
using Simple3.RCS;
|
|
using Simple3.RCS.CarTypes;
|
|
using SimpleCore.Library;
|
|
using StandardScene.Chained;
|
|
using StandardScene.Model;
|
|
using System.Collections.Concurrent;
|
|
using System.Threading;
|
|
using static StandardScene.Chained.AbstractLoopMission;
|
|
|
|
namespace StandardScene
|
|
{
|
|
|
|
|
|
public class LoopMissionStatus : AbstractLoopMissionStatus
|
|
{
|
|
|
|
}
|
|
|
|
[MissionType(Name = "环线进程", editor = typeof(LoopMission))]
|
|
[I18N.DocumentTranslation(Name = "Loop Mission", locale = "en")]
|
|
public class LoopMission : AbstractLoopMission
|
|
{
|
|
[JsonIgnore] public override MissionStatus status { get; set; } = new LoopMissionStatus();
|
|
[JsonIgnore] public Thread myThread;
|
|
[JsonIgnore] public bool started = false;
|
|
[JsonIgnore] private readonly ConcurrentDictionary<int, byte> _buttonTriggeredSiteIds = new ConcurrentDictionary<int, byte>();
|
|
public float ChargesocStandard = 30;
|
|
|
|
public float NoChargesocStandard = 80;
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// API 触发:检查站点物料状态
|
|
/// </summary>
|
|
protected override ExternalTriggerResult OnApiTrigger(int currentSiteId, LoopTask task, Car car)
|
|
{
|
|
/* var site = SimpleLib.GetSite(currentSiteId);
|
|
if (site != null && site.fields.TryGetValue("hasMaterial", out var val) && val == "true")
|
|
{
|
|
// 物料存在,使用配置目标
|
|
return ExternalTriggerResult.UseConfigTarget();
|
|
}
|
|
return ExternalTriggerResult.Fail();*/
|
|
if (car.status.enums.TryGetValue("Soc", out var soc))
|
|
{
|
|
if (float.Parse(soc) <= ChargesocStandard)
|
|
{
|
|
//使用配置目标
|
|
return ExternalTriggerResult.UseConfigTarget();
|
|
}
|
|
|
|
}
|
|
|
|
/* var plcTarget = 17;
|
|
if (plcTarget > 0)
|
|
{
|
|
// PLC 指定了目标站点
|
|
return ExternalTriggerResult.UseTarget(plcTarget);
|
|
}*/
|
|
return ExternalTriggerResult.Fail();
|
|
}
|
|
|
|
/// <summary>
|
|
/// PLC 触发:根据 PLC 信号决定目标
|
|
/// </summary>
|
|
protected override ExternalTriggerResult OnPlcTrigger(int currentSiteId, LoopTask task, Car car)
|
|
{
|
|
//var plcTarget = ReadPlcTargetSite(currentSiteId);
|
|
SiemensClient client = new SiemensClient(SiemensVersion.S7_200Smart, "127.0.0.1", 103);
|
|
var M100 = client.ReadBoolean("M100").Value;
|
|
if (M100)
|
|
{
|
|
//使用配置目标
|
|
return ExternalTriggerResult.UseConfigTarget();
|
|
|
|
}
|
|
|
|
/* var plcTarget = 17;
|
|
if (plcTarget > 0)
|
|
{
|
|
// PLC 指定了目标站点
|
|
return ExternalTriggerResult.UseTarget(plcTarget);
|
|
}*/
|
|
return ExternalTriggerResult.Fail();
|
|
}
|
|
protected override ExternalTriggerResult OnChargeTrigger(int currentSiteId, LoopTask task, Car car)
|
|
{
|
|
|
|
//使用配置目标
|
|
return ExternalTriggerResult.UseConfigTarget();
|
|
if (car.status.enums.TryGetValue("Soc", out var soc))
|
|
{
|
|
if (float.Parse(soc) >= NoChargesocStandard)
|
|
{
|
|
//使用配置目标
|
|
return ExternalTriggerResult.UseConfigTarget();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 供 ButtonMission 反射调用:登记一个需要按钮放行的站点。
|
|
/// 如果站点已经存在于字典中则忽略,避免重复放行信号堆积。
|
|
/// </summary>
|
|
/// <param name="siteId">需要放行的站点 ID,通常对应 LoopTask.CurrentStationId</param>
|
|
/// <returns>始终返回 true,表示本次按钮触发已被接受</returns>
|
|
public bool EnqueueButtonTriggerSite(int siteId)
|
|
{
|
|
if (siteId <= 0)
|
|
{
|
|
Diagnosis.Log($"按钮放行登记失败:无效站点 {siteId}", "LoopMission", true);
|
|
return false;
|
|
}
|
|
|
|
var car = FindCarArrivedAtSite(siteId);
|
|
if (car == null)
|
|
{
|
|
Diagnosis.Post($"按钮放行登记忽略:站点 {siteId} 当前没有到站车辆", "LoopMission", false);
|
|
return false;
|
|
}
|
|
|
|
if (_buttonTriggeredSiteIds.TryAdd(siteId, 0))
|
|
{
|
|
Diagnosis.Post($"按钮放行登记成功:站点 {siteId},车辆 {car.name}", "LoopMission", false);
|
|
}
|
|
else
|
|
{
|
|
Diagnosis.Post($"按钮放行已存在,忽略重复登记:站点 {siteId}", "LoopMission", false);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按钮盒触发:只有当前站点已被按钮登记过,才允许使用配置目标放行。
|
|
/// 命中后立即消费并删除,保证一次按钮只放行一次。
|
|
/// </summary>
|
|
protected override ExternalTriggerResult OnButtonTrigger(int currentSiteId, LoopTask task, Car car)
|
|
{
|
|
if (_buttonTriggeredSiteIds.TryRemove(currentSiteId, out _))
|
|
{
|
|
Diagnosis.Post($"按钮放行消费成功:站点 {currentSiteId},车辆 {car?.name}", "LoopMission", false);
|
|
return ExternalTriggerResult.UseConfigTarget();
|
|
}
|
|
|
|
return ExternalTriggerResult.Fail();
|
|
}
|
|
|
|
/* private int ReadPlcTargetSite(int siteId)
|
|
{
|
|
// 从 PLC 读取目标站点的业务逻辑
|
|
// 返回 0 表示未获取到有效目标
|
|
return 0;
|
|
}
|
|
*/
|
|
}
|
|
}
|