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 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); } } }