将 StandardScene 各插件的配置/监控窗体从 WinForms 迁移到 CycleGUI(删除 .Designer.cs/.resx,重写为 PanelBuilder 立即模式 UI,新增 CycleUiHelper 统一对话框)。 同时修复代码审核中的问题: - 后台文件写入加锁 + try/catch(ButtonBoxManager / DoorManager,对齐 LoopViewer.SaveTasks 模式) - CoderFieldsMetadata.cs 启用 #nullable enable,消除 CS8632 警告 - DummyCar 移除已废弃的 rightClickAction()/SetPosition() - CarRemoteHelper.OpenVehicleWebPage 的 Process.Start 加 try/catch - 重命名名不副实的 Mstsc()(现为打开网页) - 统一弃元命名为 _ - TrafficInterlockViewer 改用稳定 Id(GUID)做选择/编辑,替代行索引 - csproj 改用 $(CGUILibDir) 解析 CycleGUI,绝对路径收敛到 Directory.Build.props 构建:dotnet build StandardScene.sln → 0 错误,30 警告(均为历史遗留)。 注:static 单例状态重构(审核第 8 项)暂未处理,留待单独任务。
253 lines
10 KiB
C#
253 lines
10 KiB
C#
using LessokajiWeaverUtilities.Utilities;
|
||
using SimpleLite.RCS;
|
||
using SimpleLite.RCS.CarTypes;
|
||
using SimpleLite.CADTools;
|
||
using SimpleLite.Props;
|
||
using SimpleLite.UI;
|
||
using SimpleCore;
|
||
using SimpleCore.Compiler;
|
||
using SimpleCore.Library;
|
||
using SimpleCore.PropType;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Drawing;
|
||
using System.Drawing.Drawing2D;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using StandardScene.Utils;
|
||
|
||
namespace StandardScene.CarTypes
|
||
{
|
||
class ArmCarSiteFields:KivaSiteFields
|
||
{
|
||
public bool putNeedTurn = false;
|
||
}
|
||
|
||
class ArmCarTrackFields:KivaTrackFields
|
||
{
|
||
|
||
}
|
||
|
||
class ArmCarPlanFields:KivaPlanFields
|
||
{
|
||
public bool charge = false;
|
||
}
|
||
|
||
// 自 VDA5050Car.cs 下沉至 Core:ArmCar 的 siteFields 引用它(见下方 [TemplateTrackCoderSettings])。
|
||
// VDA5050 拆为独立 dll 后 ArmCar 留 Core,不能反依赖 VDA dll,故该字段类置于 Core。
|
||
class VDA5050SiteField : BasicSiteFields
|
||
{
|
||
public bool DI41 = false;
|
||
public int SleepTime = 0;
|
||
public bool workPlace = false;
|
||
}
|
||
//[TemplateTrackCoderSettings(
|
||
// priority = 1,
|
||
// templateString = "agv.BasicGo(${src.x},${src.y},${src.id},${dst.x},${dst.y},${dst.id}," +
|
||
// "${track.id},${track.Speed},${track.Reverse||(track.ReverseDst==dst.id)}," +
|
||
// "${track.CarDirectionBias},${track.EnableCarAbsoluteDirection},${track.CarAbsoluteDirection},${track.typeInfo});",
|
||
// siteFields = typeof(KivaSiteFields),
|
||
// trackFields = typeof(KivaTrackFields),
|
||
// planFields = typeof(KivaPlanFields))]
|
||
//[TemplateSiteCoderSettings(
|
||
// priority = 5,
|
||
// useVerb = "plan.action=='fetch'&&plan.curSeg==plan.segN-1",
|
||
// blockVerb = "true",
|
||
// templateString = "agv.Wait();agv.Fetch(\"${dst.name}\");agv.Wait();",
|
||
// siteFields = typeof(ArmCarSiteFields),
|
||
// trackFields = typeof(ArmCarTrackFields),
|
||
// planFields = typeof(ArmCarPlanFields))]
|
||
//[TemplateSiteCoderSettings(
|
||
// priority = 5,
|
||
// useVerb = "plan.action=='put'&&plan.curSeg==plan.segN-1",
|
||
// blockVerb = "true",
|
||
// templateString = "agv.Wait();agv.Put(${dst.putNeedTurn},\"${dst.name}\");agv.Wait();",
|
||
// siteFields = typeof(ArmCarSiteFields),
|
||
// trackFields = typeof(ArmCarTrackFields),
|
||
// planFields = typeof(ArmCarPlanFields))]
|
||
//[TemplateSiteCoderSettings(
|
||
// priority = 5,
|
||
// useVerb = "plan.action=='putEmpty'&&plan.curSeg==plan.segN-1",
|
||
// blockVerb = "true",
|
||
// templateString = "agv.Wait();agv.PutEmpty(\"${dst.name}\");agv.Wait();",
|
||
// siteFields = typeof(ArmCarSiteFields),
|
||
// trackFields = typeof(ArmCarTrackFields),
|
||
// planFields = typeof(ArmCarPlanFields))]
|
||
[TemplateSiteCoderSettings(
|
||
priority = 5,
|
||
useVerb = "plan.action=='pickFull'&&plan.curSeg==plan.segN-1",
|
||
blockVerb = "true",
|
||
templateString = "agv.Wait();agv.PickFull(\"${dst.name}\");agv.Wait();",
|
||
siteFields = typeof(ArmCarSiteFields),
|
||
trackFields = typeof(ArmCarTrackFields),
|
||
planFields = typeof(ArmCarPlanFields))]
|
||
[TemplateSiteCoderSettings(
|
||
priority = 5,
|
||
useVerb = "plan.action=='pickEmpty'&&plan.curSeg==plan.segN-1",
|
||
blockVerb = "true",
|
||
templateString = "agv.Wait();agv.PickEmpty(\"${dst.name}\");agv.Wait();",
|
||
siteFields = typeof(ArmCarSiteFields),
|
||
trackFields = typeof(ArmCarTrackFields),
|
||
planFields = typeof(ArmCarPlanFields))]
|
||
[TemplateSiteCoderSettings(
|
||
priority = 5,
|
||
useVerb = "plan.action=='putFull'&&plan.curSeg==plan.segN-1",
|
||
blockVerb = "true",
|
||
templateString = "agv.Wait();agv.PutFull(\"${dst.name}\");agv.Wait();",
|
||
siteFields = typeof(ArmCarSiteFields),
|
||
trackFields = typeof(ArmCarTrackFields),
|
||
planFields = typeof(ArmCarPlanFields))]
|
||
[TemplateSiteCoderSettings(
|
||
priority = 5,
|
||
useVerb = "plan.action=='putEmpty'&&plan.curSeg==plan.segN-1",
|
||
blockVerb = "true",
|
||
templateString = "agv.Wait();agv.PutEmpty(\"${dst.name}\");agv.Wait();",
|
||
siteFields = typeof(ArmCarSiteFields),
|
||
trackFields = typeof(ArmCarTrackFields),
|
||
planFields = typeof(ArmCarPlanFields))]
|
||
[TemplateSiteCoderSettings(
|
||
priority = 5,
|
||
useVerb = "plan.action=='MoveArm'&&plan.curSeg==plan.segN-1",
|
||
blockVerb = "true",
|
||
templateString = "agv.Wait();agv.MoveArm(${dst.MoveDirection});agv.Wait();",
|
||
siteFields = typeof(ArmCarSiteFields),
|
||
trackFields = typeof(ArmCarTrackFields),
|
||
planFields = typeof(ArmCarPlanFields))]
|
||
[TemplateSiteCoderSettings(
|
||
priority = 5,
|
||
useVerb = "dst.name=='charge'",
|
||
templateString = "agv.Wait();agv.ControlChargePort(true);agv.Wait();",
|
||
siteFields = typeof(ArmCarSiteFields),
|
||
trackFields = typeof(ArmCarTrackFields),
|
||
planFields = typeof(ArmCarPlanFields))]
|
||
|
||
[TemplateSiteCoderSettings(
|
||
priority = 5,
|
||
useVerb = "dst.name=='charge'&&plan.curSeg==0",
|
||
templateString = "agv.Wait();agv.ControlChargePort(false);",
|
||
siteFields = typeof(VDA5050SiteField))]
|
||
|
||
[CarType(Name = "ArmCar")]
|
||
[I18N.DocumentTranslation(Name = "ArmCar", locale = "en")]
|
||
public class ArmCar : GhostCar
|
||
{
|
||
public static async Task<ArmCar> Create()
|
||
{
|
||
var car = new ArmCar()
|
||
{
|
||
lstatus = "连接中",
|
||
address = "127.0.0.1",
|
||
name = $"Kiva",
|
||
haveCoordination = true,
|
||
speed = 0.3f,
|
||
};
|
||
return car;
|
||
}
|
||
private const float DrawWidth = 950, DrawLength = 650;
|
||
private readonly Pen orientPen = new Pen(Color.White, 3);
|
||
private bool twinkle = false;
|
||
protected override void draw(Graphics eGraphics)
|
||
{
|
||
try
|
||
{
|
||
float scale = 1;
|
||
var lineCap = new AdjustableArrowCap(5, 5, true);
|
||
orientPen.CustomEndCap = lineCap;
|
||
orientPen.StartCap = LineCap.RoundAnchor;
|
||
var alarmLevel = Commons.GetCarStatus(this, "AlarmLevel");
|
||
var soc = Commons.CarValue((Car)this, "Soc");
|
||
var electricCurrent = Commons.CarValue((Car)this, "ElectricCurrent");
|
||
var thresSpeed = Commons.CarValue(this, "ThresSpeed");
|
||
LadderLogic.FlipFlop(ref twinkle, 500, true, false);
|
||
Rectangle destRect = new Rectangle(
|
||
(int)((int)(-DrawWidth / 2) * scale),
|
||
(int)((int)(-DrawLength / 2) * scale),
|
||
(int)((int)DrawWidth * scale),
|
||
(int)((int)DrawLength * scale)
|
||
);
|
||
if (int.TryParse(alarmLevel, out var alarm) && alarm > 0)
|
||
{
|
||
eGraphics.FillRectangle(twinkle ? Brushes.DarkRed : Brushes.Green, destRect);
|
||
}
|
||
else if (alarmLevel == "-1" || this.siteID == -1)
|
||
eGraphics.FillRectangle(Brushes.LightSeaGreen, destRect);
|
||
else if (electricCurrent > 1)
|
||
eGraphics.FillRectangle(Brushes.YellowGreen, destRect);
|
||
else if (thresSpeed <= 0)
|
||
{
|
||
eGraphics.FillRectangle(twinkle ? Brushes.YellowGreen : Brushes.Green, destRect);
|
||
}
|
||
else if (soc < 25)
|
||
{
|
||
eGraphics.FillRectangle(twinkle ? Brushes.DarkRed : Brushes.LightSeaGreen, destRect);
|
||
}
|
||
else
|
||
eGraphics.FillRectangle(Brushes.Green, destRect);
|
||
|
||
eGraphics.DrawEllipse(Pens.Yellow, -160, -160, 320, 320);
|
||
eGraphics.DrawLine(orientPen, 0, 0, 480, 0);
|
||
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Diagnosis.Post("绘制小车异常" + ExceptionFormatter.FormatEx(e), "绘制小车异常", true);
|
||
}
|
||
}
|
||
|
||
|
||
public override string SetDisplayInfo()
|
||
{
|
||
try
|
||
{
|
||
var str = $"{name}({id})\n";
|
||
status.enums.TryGetValue("ChassisMode", out var manual);
|
||
var ms = manual == "0" ? "自动" : "手动";
|
||
status.enums.TryGetValue("Soc", out var soc);
|
||
str = $"{str}{ms}|soc:{soc}";
|
||
var alarmStr = Commons.GetCarStatus(this, "AlarmInfo");
|
||
if (alarmStr != "")
|
||
str = $"{str}|{alarmStr}";
|
||
//if (status.enums.TryGetValue("mAlarm", out var mAlarm) && mAlarm != "")
|
||
// str = $"{str}|M:{mAlarm}";
|
||
//var hasC = status.enums.TryGetValue("cAlarm", out var cAlarm) && cAlarm != "";
|
||
//if (mAlarm != "" && hasC)
|
||
// str = $"{str}|";
|
||
//if (hasC)
|
||
// str = $"{str}C:{cAlarm}";
|
||
//var L_step = status.enums.TryGetValue("ls", out var ls) && ls != "";
|
||
//if (L_step)
|
||
//{
|
||
// str = $"{str}|ls:{ls}";
|
||
//}
|
||
if (status.enums.TryGetValue("ElectricCurrent", out var electricCurrent) &&
|
||
!string.IsNullOrEmpty(electricCurrent))
|
||
{
|
||
var charging = float.Parse(electricCurrent) * 0.01f > 0 ? "充电中" : "未充电";
|
||
str = $"{str}|charge:{charging}";
|
||
}
|
||
|
||
var thresSpeed = Commons.CarValue(this, "ThresSpeed");
|
||
str = $"{str}{((thresSpeed <= 0) ? "|避障触发" : "")}";
|
||
return str;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Console.WriteLine(e);
|
||
return "bad car";
|
||
}
|
||
}
|
||
|
||
[MethodMember(Name = "进入小车管理界面", Description = "在浏览器中打开小车 Web 页面")]
|
||
[I18N.DocumentTranslation(Name = "Open vehicle management page", Description = "Open the car's management page in browser", locale = "en")]
|
||
public void OpenVehicleManagementPage()
|
||
{
|
||
CarRemoteHelper.OpenVehicleWebPage(address);
|
||
}
|
||
|
||
|
||
}
|
||
}
|