磁导航1.0内部交管和信号交互
This commit is contained in:
@@ -16,7 +16,7 @@ using StandardScene.Utils;
|
||||
namespace StandardScene.Signal
|
||||
{
|
||||
/// <summary>
|
||||
/// 第三方信号交互进程(场景 <c>scene.signal</c> 的唯一 Mission)。
|
||||
/// 第三方信号交互进程(场景 <c>scene.signal</c>:PLC 握手 / 放行;磁条交管见 <c>MagTrafficMission</c>)。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
@@ -65,9 +65,9 @@ namespace StandardScene.Signal
|
||||
|
||||
/// <summary>
|
||||
/// 西门子系列,传给 IoTClient <c>SiemensVersion</c>。
|
||||
/// 常用 <c>S7_1500</c> / <c>S7_1200</c> / <c>S7_300</c>;连字符会当成下划线解析。
|
||||
/// 机构表 PLC类型为「跟随进程」时使用本项;机构单独指定则用机构值。
|
||||
/// </summary>
|
||||
[FieldMember] public string PlcVersion = "S7_1500";
|
||||
[FieldMember] public SignalPlcType PlcVersion = SignalPlcType.S7_1500;
|
||||
|
||||
/// <summary>机构未单独填 Port 时使用的 S7 端口,默认 102。</summary>
|
||||
[FieldMember] public int PlcPort = 102;
|
||||
@@ -84,6 +84,9 @@ namespace StandardScene.Signal
|
||||
/// <summary>握手点表路径。按站点配置 JGControl / PointControl / TimedCharging / RateFlowControl。</summary>
|
||||
[FieldMember] public string HandshakePointsPath = @"Config\Signal\handshake-points.json";
|
||||
|
||||
/// <summary>机构工位表。相对路径只解析工作目录 Config/Signal。</summary>
|
||||
[FieldMember] public string DocksPath = @"Config\Signal\station-docks.json";
|
||||
|
||||
/// <summary>Execute 成功后为 true;ReloadConfig 仅在已启动时重启 Worker / 扫车。</summary>
|
||||
[JsonIgnore] private bool _started;
|
||||
|
||||
@@ -126,6 +129,12 @@ namespace StandardScene.Signal
|
||||
/// <summary>实际解析到的握手点文件绝对路径。</summary>
|
||||
public string HandshakePointsFile { get; set; }
|
||||
|
||||
/// <summary>实际解析到的工位文件绝对路径。</summary>
|
||||
public string DocksFile { get; set; }
|
||||
|
||||
/// <summary>工位 JSON 条数。</summary>
|
||||
public int DockCount { get; set; }
|
||||
|
||||
/// <summary>各机构运行态快照,供监视列表展示。</summary>
|
||||
public List<PlcStationSnapshot> Stations { get; set; } = new List<PlcStationSnapshot>();
|
||||
}
|
||||
@@ -170,23 +179,26 @@ namespace StandardScene.Signal
|
||||
public void ReloadConfig()
|
||||
{
|
||||
var stationsFile = SignalConfigStore.Resolve(StationsPath);
|
||||
var docksFile = SignalConfigStore.Resolve(DocksPath);
|
||||
var releaseFile = SignalConfigStore.Resolve(ReleasePointsPath);
|
||||
var handshakeFile = SignalConfigStore.Resolve(HandshakePointsPath);
|
||||
var stations = SignalConfigStore.Load<PlcStationModel>(stationsFile);
|
||||
var bundles = PlcConfigLoader.Load(stationsFile, docksFile);
|
||||
var points = SignalConfigStore.Load<ReleasePointModel>(releaseFile);
|
||||
var handshake = SignalConfigStore.Load<HandshakePointModel>(handshakeFile);
|
||||
|
||||
var st = (SignalInteractMissionStatus)status;
|
||||
st.StationCount = stations.Count;
|
||||
st.StationCount = bundles.Count;
|
||||
st.DockCount = bundles.Sum(b => b.Docks.Count);
|
||||
st.ReleasePointCount = points.Count;
|
||||
st.HandshakePointCount = handshake.Count;
|
||||
st.StationsFile = stationsFile;
|
||||
st.DocksFile = docksFile;
|
||||
st.ReleasePointsFile = releaseFile;
|
||||
st.HandshakePointsFile = handshakeFile;
|
||||
st.Stations = stations.Select(s => new PlcStationSnapshot { JgName = s.JgName }).ToList();
|
||||
st.Stations = bundles.Select(b => new PlcStationSnapshot { JgName = b.Station.JgName }).ToList();
|
||||
status.status = _started ? "运行中" : "配置已加载";
|
||||
Diagnosis.Post(
|
||||
$"信号配置已加载:机构 {stations.Count};握手点 {handshake.Count} @ {handshakeFile};放行点 {points.Count} @ {releaseFile}",
|
||||
$"信号配置已加载:机构 {bundles.Count},工位 {st.DockCount} @ {docksFile};握手点 {handshake.Count} @ {handshakeFile};放行点 {points.Count} @ {releaseFile}",
|
||||
"Signal", true);
|
||||
|
||||
if (_started)
|
||||
@@ -224,6 +236,24 @@ namespace StandardScene.Signal
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>CycleGUI 独立窗体编辑工位表;主键为机构名+工位编号。</summary>
|
||||
[MethodMember(Name = "打开工位列表", Description = "按 PlcStationDockModel 增删改工位点位")]
|
||||
public void OpenDocks()
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = SignalConfigStore.Resolve(DocksPath);
|
||||
ModelListPanel<PlcStationDockModel>.Open(
|
||||
"机构工位配置",
|
||||
path,
|
||||
x => x == null ? "" : $"{x.JgName}/{x.ResolvedDockId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CycleUiHelper.Alert("错误", $"打开工位列表失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>CycleGUI 独立窗体编辑握手点;主键展示为「站点号 + 信号类型」。</summary>
|
||||
[MethodMember(Name = "打开握手点列表", Description = "按站点配置 JGControl / PointControl / TimedCharging / RateFlowControl")]
|
||||
public void OpenHandshakePoints()
|
||||
@@ -266,7 +296,7 @@ namespace StandardScene.Signal
|
||||
get
|
||||
{
|
||||
lock (_workerLock)
|
||||
return _workers.Select(w => w.Runtime).ToList();
|
||||
return _workers.SelectMany(w => w.Docks).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,25 +315,28 @@ namespace StandardScene.Signal
|
||||
|
||||
/// <summary>
|
||||
/// 先停全部旧连接,再按机构表为每个非空名称建 <see cref="PlcStationWorker"/>。
|
||||
/// 机构 Port<=0 时回退进程级 <see cref="PlcPort"/>。
|
||||
/// 机构 Port<=0 时回退进程级 <see cref="PlcPort"/>;PLC类型跟随进程时用 <see cref="PlcVersion"/>。
|
||||
/// </summary>
|
||||
private void RestartWorkers()
|
||||
{
|
||||
StopWorkers();
|
||||
var stationsFile = SignalConfigStore.Resolve(StationsPath);
|
||||
var stations = SignalConfigStore.Load<PlcStationModel>(stationsFile)
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s.JgName))
|
||||
.ToList();
|
||||
var bundles = PlcConfigLoader.Load(
|
||||
SignalConfigStore.Resolve(StationsPath),
|
||||
SignalConfigStore.Resolve(DocksPath));
|
||||
|
||||
var created = new List<PlcStationWorker>();
|
||||
lock (_workerLock)
|
||||
{
|
||||
foreach (var station in stations)
|
||||
foreach (var bundle in bundles)
|
||||
{
|
||||
var station = bundle.Station;
|
||||
var port = station.Port > 0 ? station.Port : PlcPort;
|
||||
var runtime = new PlcStationRuntime(station);
|
||||
var session = new SiemensPlcSession(PlcVersion, station.Ip, port, PlcSlot);
|
||||
var worker = new PlcStationWorker(runtime, session, PlcPollMs, RefreshStatus);
|
||||
var sync = new object();
|
||||
var runtimes = bundle.Docks
|
||||
.Select(d => new PlcStationRuntime(station, d, sync))
|
||||
.ToList();
|
||||
var session = new SiemensPlcSession(ResolvePlcType(station), station.Ip, port, PlcSlot);
|
||||
var worker = new PlcStationWorker(station, runtimes, session, sync, PlcPollMs, RefreshStatus);
|
||||
_workers.Add(worker);
|
||||
created.Add(worker);
|
||||
}
|
||||
@@ -315,6 +348,15 @@ namespace StandardScene.Signal
|
||||
PushStatus();
|
||||
}
|
||||
|
||||
/// <summary>机构选跟随进程(含旧 JSON 缺省 0)时用进程 PlcVersion;进程若也是跟随进程则按 S7_1500。</summary>
|
||||
private string ResolvePlcType(PlcStationModel station)
|
||||
{
|
||||
var type = station.PlcType == SignalPlcType.跟随进程 ? PlcVersion : station.PlcType;
|
||||
if (type == SignalPlcType.跟随进程)
|
||||
type = SignalPlcType.S7_1500;
|
||||
return type.ToString();
|
||||
}
|
||||
|
||||
/// <summary>清空列表后再 Stop,避免扫车在停连接过程中仍拿到旧 Runtime。</summary>
|
||||
private void StopWorkers()
|
||||
{
|
||||
@@ -345,7 +387,7 @@ namespace StandardScene.Signal
|
||||
{
|
||||
List<PlcStationSnapshot> snaps;
|
||||
lock (_workerLock)
|
||||
snaps = _workers.Select(w => w.Runtime.ToSnapshot()).ToList();
|
||||
snaps = _workers.SelectMany(w => w.Docks.Select(d => d.ToSnapshot())).ToList();
|
||||
|
||||
var st = (SignalInteractMissionStatus)status;
|
||||
st.Stations = snaps;
|
||||
|
||||
Reference in New Issue
Block a user