using System;
using SimpleCore.Library;
using StandardScene.Signal.Model;
namespace StandardScene.Signal.Plc
{
///
/// 单个机构的运行态(不进 JSON)。扫车线程改写目标写字节,PLC Worker 负责真正下发。
///
///
/// 赋值 会把 置 false,下一拍 Worker 发现
/// 目标与回读不一致就会重写 PLC。回读与目标一致后再标成功,AutoLeave 才继续往下一状态走。
/// 所有读写应在 内进行。
///
public sealed class PlcStationRuntime
{
private SignalWriteValue _writeSignal;
private SignalReadValue _readSignal;
private SignalWriteValue _readWriteSignal;
public PlcStationRuntime(PlcStationModel config)
{
Config = config ?? throw new ArgumentNullException(nameof(config));
}
/// 本机构静态配置(IP、DB 地址、地标、机构类型)。
public PlcStationModel Config { get; }
/// 扫车线程与 PLC Worker 共用运行态,写入时加此锁。
public object Sync { get; } = new object();
/// PLC→调度:允许进入 / 允许离开 / 无状态。变化时打诊断。
public SignalReadValue ReadSignal
{
get => _readSignal;
set
{
if (_readSignal != value)
Diagnosis.Log($"{Config.JgName} 读信号 {_readSignal} → {value}", "PLC", true);
_readSignal = value;
}
}
///
/// 调度→PLC 的目标写字节。赋值即视为尚未写成功,驱动 Worker 重写。
///
public SignalWriteValue WriteSignal
{
get => _writeSignal;
set
{
if (_writeSignal != value)
Diagnosis.Log($"{Config.JgName} 写信号 {_writeSignal} → {value}", "PLC", true);
_writeSignal = value;
WriteSuccess = false;
}
}
/// 从写地址回读到的当前值,用来确认 PLC 是否已吃进目标字节。
public SignalWriteValue ReadWriteSignal
{
get => _readWriteSignal;
set
{
if (_readWriteSignal != value)
Diagnosis.Log($"{Config.JgName} 回读写值 {_readWriteSignal} → {value}", "PLC", true);
_readWriteSignal = value;
}
}
/// 已报到在机构内的 AGV 号;0 表示没有。Arrived / 上线自动到位 时写入。
public int InAgvNo { get; set; }
/// 已获准进入、正在往机构开的 AGV 号;到位或离站清空后为 0。
public int RequestInAgvNo { get; set; }
/// 最近一拍 PLC 读写是否成功。心跳或读写失败会立刻变 false。
public bool IsConnected { get; set; }
/// 目标写字节是否已与 PLC 回读一致。改 WriteSignal 时自动清掉。
public bool WriteSuccess { get; set; }
/// 内存侧心跳翻转标志,供监视面板看到 Worker 在跑;真正写 PLC 的是 HeartDb 位翻转。
public bool Heart { get; set; }
/// 最近一次断线或周期异常原因,连接正常时清空。
public string LastError { get; set; } = "";
/// 拷贝一份给 MissionStatus / 监视列表,避免 UI 直接绑运行态。
public PlcStationSnapshot ToSnapshot() => new PlcStationSnapshot
{
JgName = Config.JgName,
IsConnected = IsConnected,
ReadSignal = ReadSignal.ToString(),
WriteSignal = WriteSignal.ToString(),
ReadWriteSignal = ReadWriteSignal.ToString(),
InAgvNo = InAgvNo,
RequestInAgvNo = RequestInAgvNo,
WriteSuccess = WriteSuccess,
Heart = Heart,
LastError = LastError ?? ""
};
}
}