using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Rs.MotionPlat.Flow;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace Rs.MotionPlat.Commom
{
///
/// 排料通讯
///
public class Scheduling
{
///
/// 指令
///
public EInstruction Instruction { get; set; }
///
/// 组ID
///
public int GroupID { get; set; }
///
/// 周转ID
///
public int TurnoverID { get; set; }
///
/// 发送或接收时间
///
public DateTime Time { get; set; } = DateTime.Now;
public override string ToString() => JsonConvert.SerializeObject(this, new StringEnumConverter());
}
public class SchedulingConnectionInfo : Scheduling
{
public EType Type { get; set; }
public enum EType
{
Scheduling,
ScannerMotion
}
}
///
/// 上下料
///
public class SchedulingMaterial : Scheduling
{
public List ActionItems { get; set; }
public SchedulingMaterial() { }
}
public struct ActionItem
{
///
/// 产品条码
///
public string SN;
///
/// 取料信息
///
public ActionInfo Load;
///
/// 放料信息
///
public ActionInfo To;
public ActionItem(ActionInfo load, ActionInfo to,string _SN)
{
SN=_SN;
Load = load;
To = to;
}
}
public struct ActionInfo
{
///
/// 类型
///
public TurnoverType Type;
///
/// 分区名
///
public string RangeName;
///
/// 层(仅多功能时用)
///
public int Floor;
///
/// 料盘索引(仅周转盘用)
///
public int Index;
public ActionInfo(TurnoverType type, int floor, string rangeName, int index)
{
Type = type;
RangeName = rangeName;
Floor = floor;
Index = index;
}
}
public class TurnoverInfos : Scheduling
{
///
/// 周转信息
///
public List Infos { get; set; }
///
/// 跳过取放信息
///
public List SkipInfos { get; set; }
}
public class TurnoverInfo
{
#region 冗余字段
[JsonIgnore]
public EInstruction Instruction;
[JsonIgnore]
public int GroupID;
[JsonIgnore]
public int TurnoverID;
[JsonIgnore]
public string GUID = string.Empty;
[JsonIgnore]
public ETaskMode taskMode = ETaskMode.Load;
#endregion
public string SN;
///
/// 来源类型
///
public TurnoverType FromType;
///
/// 来源料仓所在层,如是周转盘则为0
///
public int FromFloor;
///
/// 来源索引
///
public int FromIndex;
///
/// 目标类型
///
public TurnoverType ToType;
///
/// 目标料仓所在层,如是周转盘则为0
///
public int ToFloor;
///
/// 目标索引
///
public int ToIndex;
///
/// 使用的吸嘴编号
///
public int SuckerNo;
public bool Dealed;
public TurnoverInfo(EInstruction _Instruction,int _GroupID,int _TurnoverID,string _SN,TurnoverType fromType, int fromFloor, int fromIndex, TurnoverType toType, int toFloor, int toIndex, int suckerNo,bool _Dealed=false)
{
Dealed = _Dealed;
Instruction = _Instruction;
GroupID = _GroupID;
TurnoverID = _TurnoverID;
SN = _SN;
FromType = fromType;
FromFloor = fromFloor;
FromIndex = fromIndex;
ToType = toType;
ToFloor = toFloor;
ToIndex = toIndex;
SuckerNo = suckerNo;
}
public TurnoverInfo() { }
}
public struct SkipInfo
{
public TurnoverType Type;
public int Floor;
public int Index;
public SkipCause Cause;
public string Message;
public SkipInfo(TurnoverType type, int floor, int index, SkipCause cause, string message)
{
Type = type;
Floor = floor;
Index = index;
Cause = cause;
Message = message;
}
}
public enum SkipCause
{
Empty, Error
}
public enum TurnoverType
{
///
/// 未知
///
Unknown,
///
/// 待测料仓
///
ToBeTested,
///
/// OK仓
///
Passed,
///
/// NG仓
///
Failed,
///
/// 多功能仓
///
Multifunction,
///
/// 周转盘
///
Turnover,
///
/// 换料缓存
///
Buffer,
///
/// 重测缓存盘
///
BufferTray,
///
/// 清洗料盘
///
CleanPad,
///
/// 测试治具
///
Tester
}
///
/// 取料失败
///
public class SchedulingTakingError : Scheduling
{
///
/// ID
///
public int ID { get; set; }
///
/// 周转类型
///
public TurnoverType Type { get; set; }
///
/// 当前层
///
public int Floor { get; set; }
///
/// 托盘索引
///
public int Index { get; set; }
///
/// 使用的吸嘴索引
///
public int SuckerIndex { get; set; } = -1;
///
/// 处理方式,中控返回时提供
///
public TakeErrorHandle Handle { get; set; }
}
public enum TakeErrorHandle
{
///
/// 重取
///
Retry,
///
/// 跳过当前穴位
///
Skip,
///
/// 结束本轮取料
///
End
}
public class SchedulingSiloBase : Scheduling
{
public ESiloType SiloType { get; set; }
public EMultifunctionType MultifunctionType { get; set; }
public enum ESiloType
{
///
/// 待测料仓
///
ToBeTested,
///
/// OK仓
///
Passed,
///
/// NG仓
///
Failed,
///
/// 多功能仓
///
Multifunction
}
public enum EMultifunctionType
{
///
/// 无
///
None,
///
/// 默认
///
Default,
///
/// 第二层
///
Floor1,
///
/// 第三层
///
Floor2,
///
/// 第四层
///
Floor3
}
}
///
/// 托盘产品分区范围
///
public class TrayProductRange : SchedulingSiloBase
{
///
/// 该分区的名称
///
public string Name { get; set; }
public int Left { get; set; }
public int Top { get; set; }
public int Right { get; set; }
public int Bottom { get; set; }
}
public class SiloRearrange : SchedulingSiloBase
{
public enum EOrientation { Horizontal, Vertical }
///
/// 排列方向
///
public EOrientation Orientation { get; set; }
}
public class SchedulingSilo : SchedulingSiloBase
{
public enum ESwitchOrientation
{
///
/// 切到下一个
///
Next,
///
/// 切回上一个
///
Previous
}
public enum ESiloStatus
{
///
/// 停止
///
Stopped,
///
/// 就绪
///
Standby,
///
/// 切换中
///
Switching,
///
/// 空,无料盘
///
None
}
///
/// 料仓状态
///
public ESiloStatus SiloStatus { get; set; }
///
/// 切换方向
///
public ESwitchOrientation Orientation { get; set; }
///
/// 料仓当前层 == 时无效
///
public int SiloFloor { get; set; }
}
public class SchedulingMoveScanner : Scheduling
{
///
/// 点位 1~32 (<= 100) 托盘穴位点位, 101~102 (>100) 托盘条码点位
///
public int Point { get; set; }
}
public class SchedulingMoveScannerResult : SchedulingMessage
{
///
/// 当前点位或移动中的目标点位
///
public int Point { get; set; }
///
/// 当前移动状态
///
public EMoveState MoveState { get; set; }
public enum EMoveState
{
///
/// 已到达
///
Ready,
///
/// 移动中
///
Moving,
///
/// 发生错误,无法恢复
///
Error,
///
/// 中断,出现异常中断,可恢复
///
Interrupt
}
}
///
/// 排料报警
///
//public class SchedulingAlarms : Scheduling
//{
// ///
// /// 报警项,如果item1 == item2 将会认作同一报警
// ///
// public IList Alarms { get; set; }
// public struct AlarmItem : IAlarmItem
// {
// ///
// /// 报警序号
// ///
// public int NO { get; set; }
// ///
// /// 引发报警的节点UID
// ///
// public long NodeUID { get; set; }
// ///
// /// 引发报警节点的穴位索引(如:周转盘穴位 3)
// ///
// public int? Index
// {
// readonly get => Indexes is HashSet list && list.Count > 0 ? list.Last() : null;
// set
// {
// if (value is not int index) return;
// HashSet list = Indexes ??= new();
// if (!list.Contains(index))
// {
// list.Add(index);
// }
// }
// }
// ///
// /// 引发报警的节点的穴位索引列表
// ///
// public HashSet Indexes { get; set; }
// ///
// /// 报警标签
// ///
// public string Tag { get; set; }
// ///
// /// 该报警是否会造成停机
// ///
// public bool Pause { get; set; }
// ///
// /// 报警等级
// ///
// public AlarmLevel Level { get; set; }
// ///
// /// 已在别的地方展示,只收录,不弹窗
// ///
// public bool ShowElsewhere { get; set; }
// ///
// /// 报警消息英文版
// ///
// public string EN { get; set; }
// ///
// /// 报警消息中文版
// ///
// public string ZH { get; set; }
// readonly IReadOnlySet IAlarmItem.Indexes => Indexes;
// public readonly string GetMessage(CultureInfo culture)
// {
// return culture.TwoLetterISOLanguageName.ToLower() switch
// {
// "en" => EN,
// _ => ZH,
// };
// }
// public readonly string ToDescription(CultureInfo culture) => $"{GetString(nameof(NO), culture)}: {NO} "
// + $"{GetString(nameof(NodeUID), culture)}: {NodeUID} "
// + $"{GetString(nameof(Index), culture)}: {Indexes.ToStringEx()} "
// + $"{GetString(nameof(Tag), culture)}: {Tag} "
// + $"{GetString(nameof(Pause), culture)}: {Pause} "
// + $"{GetString(nameof(EN), culture)}: {EN} "
// + $"{GetString(nameof(ZH), culture)}: {ZH}";
// public override readonly bool Equals(object obj) => obj is IAlarmItem other && Equals(other);
// ///
// /// 相等比较方法
// ///
// ///
// ///
// public readonly bool Equals(IAlarmItem other) => NO == other.NO && NodeUID == other.NodeUID && SequenceEqual(Indexes, other.Indexes) && Tag == other.Tag;
// public override readonly int GetHashCode() => HashCode.Combine(NO, NodeUID, Indexes, Tag);
// public override readonly string ToString() => $"{Tag} No.{NO} {NodeUID} {Indexes.ToStringEx()} {ZH}";
// public static bool operator ==(AlarmItem left, AlarmItem right) => left.Equals(right);
// public static bool operator !=(AlarmItem left, AlarmItem right) => !(left == right);
// }
// public SchedulingAlarms() { }
// public SchedulingAlarms(params AlarmItem[] items) => Alarms = items;
//}
///
/// 排料状态信息
///
public class SchedulingStatusInfo : Scheduling
{
///
/// 查询或切换时的状态类型
///
public InfoType Type { get; set; }
///
/// 查询时返回或切换时需要切换到的状态信息
///
public string Info { get; set; }
public bool TryConvertInfoTo(out TEnum result) where TEnum : struct
{
try
{
if (typeof(TEnum).IsEnum)
return Enum.TryParse(Info, true, out result);
result = (TEnum)Convert.ChangeType(Info, typeof(TEnum));
return true;
}
catch
{
result = default;
return false;
}
}
public enum InfoType
{
///
/// 上下料状态,
///
State,
///
/// 设备运行状态,
///
RunStatus,
///
/// 运行模式,
///
RunMode,
///
/// 初始化状态,
///
InitializeState,
///
/// 物料分配模式(带料OR不带料),
///
AssignMode,
///
/// 温度,
///
Temperature,
///
/// 气压(double)
///
AirPressure
}
}
///
/// 排料消息
///
public class SchedulingMessage : Scheduling
{
///
/// 消息
///
public string Message { get; set; }
}
///
/// 中控状态
///
public class MachineState : SchedulingMessage
{
///
/// 设备状态
///
public ERunState State { get; set; }
public MachineState() { }
}
///
/// 排料结果
///
public class SchedulingResult : SchedulingMessage
{
///
/// 结果
///
public bool Result { get; set; } = true;
///
/// 设备状态
///
public ERunState State { get; set; }
public SchedulingResult() { }
}
///
/// 排料弹窗请求
///
public class SchedulingMessageBox : SchedulingMessage
{
[Flags]
public enum ETipButton
{
None = 0,
Yes = 1 << 0,
No = 1 << 1,
Ok = 1 << 2,
Cancel = 1 << 3,
Retry = 1 << 4,
Skip = 1 << 5,
YesNo = Yes | No,
OkCancel = Ok | Cancel,
OkRetryCancel = Ok | Retry | Cancel,
RetrySkip = Retry | Skip
}
///
/// 请求弹窗按钮,返回用户点击的按钮
///
public ETipButton Button { get; set; } = ETipButton.YesNo;
///
/// 请求的ID,返回时将带上该id作为标识
///
public int ID { get; set; }
///
/// 弹窗标题
///
public string Title { get; set; }
///
/// 图片路径,如为null或则不显示图片
///
public string PicturePath { get; set; }
///
/// 字体大小
///
public double FontSize { get; set; } = 15;
///
/// 窗口宽度
///
public double WindowWidth { get; set; } = 800;
///
/// 窗口高度
///
public double WindowHeight { get; set; } = 800;
///
/// 倒计时,单位秒,小于0不启用
///
public int Countdown { get; set; } = System.Threading.Timeout.Infinite;
///
/// 倒计时结束时按下的按钮
///
public ETipButton CountdownResult { get; set; } = ETipButton.Yes;
public SchedulingMessageBox() { }
}
///
/// 指令
///
public enum EInstruction
{
///
/// 查询连接功能 发送: 回复:
///
InquireConnectionInfo,
///
/// 上下料 发送: 回复:
///
LoadAndUnload,
///
/// 排料机回传上下料结果 排料机发送
///
LoadAndUnloadResult,
///
/// 取消当前 执行中的排料指令,发送: 回复:
///
CancelLoadAndUnload,
///
/// 查询状态 发送: 回复:
///
InquireStatus,
///
/// 切换状态 发送: 回复:
///
SwitchStatus,
///
/// 清除报警 发送: 回复:
///
ClearAlarm,
///
/// 获取配方列表 发送: 回复:
///
GetRecipeList,
///
/// 设置配方 发送: 回复:
///
SetRecipe,
///
/// 获取当前配方 发送: 回复:
///
GetCurrentRecipe,
///
/// 周转盘就绪查询 排料机发送 中控回复:
///
TurnoverReady,
///
/// 通知排料运行状态变更 发送 回复:
///
ChangeState,
///
/// 弹消息提示窗 排料机发送 中控回复:
///
ShowMessage,
///
/// 取消消息弹窗 排料机发送 中控回复:
///
CloseMessage,
///
/// 设备按钮按下 排料机发送 中控回复: ,
/// 其中内容为枚举.ToString()
///
MachineButtonDown,
///
/// 设备按钮松开 排料机发送 中控回复: ,
/// 其中内容为枚举.ToString()
///
MachineButtonUp,
///
/// 设置托盘产品分区范围 发送: 回复:
///
TrayProductRange,
///
/// 清空托盘产品分区范围 发送: 回复:
///
ClearTrayProductRange,
///
/// 请求切换料盘 发送 回复:
///
RequestSwitchTray,
///
/// 开始切换料盘 发送 回复:
///
BeginSwitchTray,
///
/// 查询料仓状态 发送 回复:
///
InquireSiloStatus,
///
/// 移动扫码枪 发送 回复收到的:
///
MoveScanner,
///
/// 查询移动扫码枪结果 发送 回复:
///
InquireMoveScannerState,
///
/// 设置报警 排料机发送 中控回复收到的
///
SetAlarms,
///
/// 取消报警 排料机发送 中控回复收到的
///
CancelAlarms,
///
/// 最后一盘, 发送 回复
///
IsLastBeforeTray,
///
/// 结束上新, 发送 回复
///
EndInput,
///
/// 取料失败, 排料机发送 回复, 里提供接下来该做的处理方式
///
TakingError,
///
/// 取消取料失败, 排料机发送, 里提供接下来该做的处理方式
///
CancelTakingError,
///
/// 重排料仓当前料盘物料方向 发送: 回复:
///
Rearrange,
///
/// 重排料仓当前料盘物料方向的结果 发送:
///
RearrangeResult,
///
/// 扫描条码, 中控发送 回复
///
ScanBarcode
}
///
/// 运行模式
///
public enum ERunMode
{
///
/// 手动
///
Manual,
///
/// 自动
///
Automatic
}
///
/// 设备运行状态
///
public enum ERunStatus
{
///
/// 已开始
///
Started,
///
/// 已停止
///
Stopped,
///
/// 报警中
///
InAlarm,
///
/// 急停中
///
EMGStop
}
///
/// 初始化状态
///
public enum EInitializeState
{
///
/// 未初始化
///
Uninitialized,
///
/// 初始化中
///
Initializing,
///
/// 已初始化
///
Initialized
}
///
/// 物料分配模式
///
public enum EAssignMode
{
///
/// 正常
///
Normal,
///
/// 无料空跑
///
NoDevice
}
///
/// 设备按钮
///
public enum EMachineButton
{
Start, Stop, EMGStop, Initialize, Ok, Cancel, Retry, Skip, Lighting, Door
}
///
/// 上下料状态
///
public enum ERunState
{
///
/// 等待指令
///
Waiting,
///
/// 忙碌中
///
Busying,
///
/// 下料中
///
Unloading,
///
/// 发生错误,无法恢复
///
Error,
///
/// 中断,出现异常中断,可恢复
///
Interrupt
}
}