帮助手册

接收端源码

JmSetupSheetReceiver 将 POST JSON 还原为 SetupsheetData,并输出中英对照明文(控制台 + 同名 .txt)。完整工程见 receiver/

学习入口:SetupSheetOps.DeserializeToPlainTextSetupSheetStore.Latest。命令:text / tools / images

文件说明
Program.csHttpListener + 控制台命令
SetupSheetOps.cs反序列化、明文、对象操作
Models/SetupsheetModels.cs强类型模型(全字段中文注释)
lib/Newtonsoft.Json.dllJSON 库

Program.cs

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using JmSetupSheetReceiver.Models;

namespace JmSetupSheetReceiver
{
	/// <summary>
	/// 机明程序单对外提交 — 接收端演示源码(学习 / 联调用)。
	/// <para>
	/// 接收 POST JSON 后用 Newtonsoft.Json 还原为 <see cref="SetupsheetData"/> 强类型对象,
	/// 控制台可 summary / tools / images 等命令查看与操作。
	/// </para>
	/// <para>
	/// 默认:http://127.0.0.1:1234/
	/// 参数:JmSetupSheetReceiver.exe [监听前缀] [--fail] [--pretty]
	/// </para>
	/// </summary>
	internal static class Program
	{
		private static bool _forceFail;
		private static bool _prettyJson;
		private static volatile bool _running = true;

		private static int Main(string[] args)
		{
			string prefix = "http://127.0.0.1:1234/";
			ParseArgs(args, ref prefix);

			string receivedDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Received");
			Directory.CreateDirectory(receivedDir);

			if (!HttpListener.IsSupported)
			{
				Console.WriteLine("当前系统不支持 HttpListener。");
				return 1;
			}

			var listener = new HttpListener();
			listener.Prefixes.Add(prefix);

			try
			{
				listener.Start();
			}
			catch (HttpListenerException ex)
			{
				Console.WriteLine("无法监听 {0}", prefix);
				Console.WriteLine("原因: {0}", ex.Message);
				Console.WriteLine();
				Console.WriteLine("提示: 非管理员账户监听 localhost 以外地址时,可能需要先执行:");
				Console.WriteLine("  netsh http add urlacl url={0} user=%USERNAME%", prefix);
				return 2;
			}

			PrintBanner(prefix, receivedDir);
			SetupSheetOps.PrintHelp();

			Console.CancelKeyPress += (s, e) =>
			{
				e.Cancel = true;
				_running = false;
				try { listener.Stop(); } catch { }
			};

			// 监听循环放后台,主线程跑命令行,便于操作已还原对象
			var acceptThread = new Thread(() => AcceptLoop(listener, receivedDir))
			{
				IsBackground = true,
				Name = "HttpAccept"
			};
			acceptThread.Start();

			RunCommandLoop(receivedDir);

			_running = false;
			try { listener.Stop(); } catch { }
			try { listener.Close(); } catch { }
			return 0;
		}

		private static void AcceptLoop(HttpListener listener, string receivedDir)
		{
			while (_running && listener.IsListening)
			{
				HttpListenerContext context;
				try
				{
					context = listener.GetContext();
				}
				catch (HttpListenerException)
				{
					break;
				}
				catch (ObjectDisposedException)
				{
					break;
				}

				ThreadPool.QueueUserWorkItem(_ => HandleRequest(context, receivedDir));
			}
		}

		private static void ParseArgs(string[] args, ref string prefix)
		{
			if (args == null) return;
			foreach (string raw in args)
			{
				if (string.IsNullOrWhiteSpace(raw)) continue;
				string a = raw.Trim();
				if (string.Equals(a, "--fail", StringComparison.OrdinalIgnoreCase)
					|| string.Equals(a, "-fail", StringComparison.OrdinalIgnoreCase))
				{
					_forceFail = true;
					continue;
				}
				if (string.Equals(a, "--pretty", StringComparison.OrdinalIgnoreCase)
					|| string.Equals(a, "-pretty", StringComparison.OrdinalIgnoreCase))
				{
					_prettyJson = true;
					continue;
				}
				if (a.StartsWith("-"))
				{
					Console.WriteLine("未知参数: {0}(已忽略)", a);
					continue;
				}
				prefix = a;
				if (!prefix.EndsWith("/")) prefix += "/";
			}
		}

		private static void PrintBanner(string prefix, string receivedDir)
		{
			Console.WriteLine("================================================");
			Console.WriteLine(" 机明程序单接收端演示  JmSetupSheetReceiver");
			Console.WriteLine("================================================");
			Console.WriteLine("监听地址 : {0}", prefix);
			Console.WriteLine("落盘目录 : {0}", receivedDir);
			Console.WriteLine("GET 探活 : 浏览器打开上述地址");
			Console.WriteLine("POST     : JSON → 对象 + JSON/明文落盘 → {0}",
				_forceFail ? "500 (--fail)" : "200");
			if (_prettyJson) Console.WriteLine("落盘格式 : 美化 JSON (--pretty)");
			Console.WriteLine("明文     : 控制台打印 + Received\\同名.txt(预览图仅字节摘要)");
			Console.WriteLine("对象访问 : SetupSheetStore.Latest  / 下方控制台命令");
			Console.WriteLine("按 Ctrl+C 或输入 quit 退出");
			Console.WriteLine("================================================");
			Console.WriteLine();
		}

		private static void RunCommandLoop(string receivedDir)
		{
			while (_running)
			{
				Console.Write("> ");
				string line;
				try
				{
					line = Console.ReadLine();
				}
				catch
				{
					break;
				}
				if (line == null) break;
				line = line.Trim();
				if (line.Length == 0) continue;

				string cmd = line;
				string arg = null;
				int sp = line.IndexOf(' ');
				if (sp > 0)
				{
					cmd = line.Substring(0, sp).Trim();
					arg = line.Substring(sp + 1).Trim();
				}

				try
				{
					DispatchCommand(cmd, arg, receivedDir);
				}
				catch (Exception ex)
				{
					Console.WriteLine("命令错误: {0}", ex.Message);
				}
			}
		}

		private static void DispatchCommand(string cmd, string arg, string receivedDir)
		{
			if (string.Equals(cmd, "quit", StringComparison.OrdinalIgnoreCase)
				|| string.Equals(cmd, "exit", StringComparison.OrdinalIgnoreCase))
			{
				_running = false;
				return;
			}
			if (string.Equals(cmd, "help", StringComparison.OrdinalIgnoreCase)
				|| string.Equals(cmd, "?", StringComparison.OrdinalIgnoreCase))
			{
				SetupSheetOps.PrintHelp();
				return;
			}

			var data = SetupSheetStore.Latest;
			if (string.Equals(cmd, "summary", StringComparison.OrdinalIgnoreCase)
				|| string.Equals(cmd, "s", StringComparison.OrdinalIgnoreCase))
			{
				SetupSheetOps.PrintSummary(data);
				return;
			}
			if (string.Equals(cmd, "text", StringComparison.OrdinalIgnoreCase)
				|| string.Equals(cmd, "plain", StringComparison.OrdinalIgnoreCase))
			{
				if (data == null)
				{
					Console.WriteLine("尚无已还原对象。请先 POST 或 load。");
					return;
				}
				SetupSheetOps.PrintPlainText(data);
				string txtPath = Path.Combine(receivedDir, "latest-plain.txt");
				SetupSheetOps.SavePlainText(data, txtPath);
				Console.WriteLine("明文已另存: {0}", txtPath);
				return;
			}
			if (string.Equals(cmd, "tools", StringComparison.OrdinalIgnoreCase)
				|| string.Equals(cmd, "t", StringComparison.OrdinalIgnoreCase))
			{
				SetupSheetOps.PrintToolPaths(data);
				return;
			}
			if (string.Equals(cmd, "tool", StringComparison.OrdinalIgnoreCase))
			{
				if (string.IsNullOrEmpty(arg))
				{
					Console.WriteLine("用法: tool <刀路名|NC名|刀具名>");
					return;
				}
				SetupSheetOps.PrintToolPathDetail(SetupSheetOps.FindToolPath(data, arg));
				return;
			}
			if (string.Equals(cmd, "positions", StringComparison.OrdinalIgnoreCase)
				|| string.Equals(cmd, "pos", StringComparison.OrdinalIgnoreCase))
			{
				SetupSheetOps.PrintSummary(data);
				return;
			}
			if (string.Equals(cmd, "images", StringComparison.OrdinalIgnoreCase)
				|| string.Equals(cmd, "img", StringComparison.OrdinalIgnoreCase))
			{
				if (data == null)
				{
					Console.WriteLine("尚无已还原对象。请先 POST 一份程序单 JSON。");
					return;
				}
				string dir = Path.Combine(receivedDir, "images_" + DateTime.Now.ToString("yyyyMMdd-HHmmss"));
				int n = SetupSheetOps.SavePreviewImages(data, dir);
				Console.WriteLine("共导出 {0} 张预览图 → {1}", n, dir);
				return;
			}
			if (string.Equals(cmd, "dump", StringComparison.OrdinalIgnoreCase))
			{
				if (data == null)
				{
					Console.WriteLine("尚无已还原对象。");
					return;
				}
				string path = Path.Combine(receivedDir, "latest-object.json");
				File.WriteAllText(path, SetupSheetOps.Serialize(data), new UTF8Encoding(false));
				Console.WriteLine("已将对象重新序列化到: {0}", path);
				return;
			}
			if (string.Equals(cmd, "path", StringComparison.OrdinalIgnoreCase))
			{
				Console.WriteLine("原始 JSON: {0}", SetupSheetStore.LatestJsonPath ?? "(尚无)");
				Console.WriteLine("明文 TXT : {0}", SetupSheetStore.LatestTxtPath ?? "(尚无)");
				return;
			}
			if (string.Equals(cmd, "load", StringComparison.OrdinalIgnoreCase))
			{
				// 从已落盘文件再次还原,方便离线调试
				string file = arg;
				if (string.IsNullOrEmpty(file))
					file = SetupSheetStore.LatestJsonPath;
				if (string.IsNullOrEmpty(file) || !File.Exists(file))
				{
					Console.WriteLine("用法: load [json文件路径]");
					return;
				}
				string json = File.ReadAllText(file, Encoding.UTF8);
				var sheet = SetupSheetOps.Deserialize(json);
				string txtPath = Path.ChangeExtension(file, ".txt");
				if (string.Equals(Path.GetExtension(file), ".txt", StringComparison.OrdinalIgnoreCase))
					txtPath = Path.Combine(receivedDir, "loaded-plain.txt");
				SetupSheetOps.SavePlainText(sheet, txtPath);
				SetupSheetStore.SetLatest(sheet, file, txtPath);
				Console.WriteLine("已从文件还原对象: {0}", file);
				Console.WriteLine("明文已写入: {0}", txtPath);
				SetupSheetOps.PrintPlainText(sheet);
				return;
			}

			Console.WriteLine("未知命令: {0}  (输入 help 查看)", cmd);
		}

		private static void HandleRequest(HttpListenerContext context, string receivedDir)
		{
			HttpListenerRequest request = context.Request;
			HttpListenerResponse response = context.Response;
			string method = request.HttpMethod ?? "";
			string path = request.Url != null ? request.Url.AbsolutePath : "/";

			try
			{
				if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase))
				{
					string help =
						"JmSetupSheetReceiver — 机明程序单接收端演示\r\n\r\n" +
						"POST application/json → 还原为 SetupsheetData,落盘 JSON 与明文 TXT。\r\n" +
						"成功返回 HTTP 200: {\"success\":true,\"message\":\"received\"}\r\n" +
						"控制台命令: summary / text / tools / tool <名> / images / dump / load\r\n";
					WriteText(response, 200, "text/plain; charset=utf-8", help);
					Console.WriteLine("[{0:HH:mm:ss}] GET {1} -> 200 (probe)", DateTime.Now, path);
					return;
				}

				if (!string.Equals(method, "POST", StringComparison.OrdinalIgnoreCase))
				{
					WriteText(response, 405, "text/plain; charset=utf-8", "Method Not Allowed. Use POST.");
					Console.WriteLine("[{0:HH:mm:ss}] {1} {2} -> 405", DateTime.Now, method, path);
					return;
				}

				string body;
				using (var reader = new StreamReader(request.InputStream, request.ContentEncoding ?? Encoding.UTF8))
				{
					body = reader.ReadToEnd();
				}

				SetupsheetData sheet = null;
				string deserializeError = null;
				try
				{
					sheet = SetupSheetOps.Deserialize(body);
				}
				catch (Exception ex)
				{
					deserializeError = ex.Message;
				}

				string toSave = body ?? string.Empty;
				if (_prettyJson && sheet != null)
				{
					try { toSave = SetupSheetOps.Serialize(sheet); }
					catch { /* 保留原文 */ }
				}

				string fileName = DateTime.Now.ToString("yyyyMMdd-HHmmss-fff") + ".json";
				string filePath = Path.Combine(receivedDir, fileName);
				File.WriteAllText(filePath, toSave, new UTF8Encoding(false));

				int len = body == null ? 0 : Encoding.UTF8.GetByteCount(body);

				if (sheet != null)
				{
					string txtPath = Path.ChangeExtension(filePath, ".txt");
					SetupSheetOps.SavePlainText(sheet, txtPath);
					SetupSheetStore.SetLatest(sheet, filePath, txtPath);
					Console.WriteLine();
					Console.WriteLine("[{0:HH:mm:ss}] POST {1} -> 对象已还原 (SetupsheetData)", DateTime.Now, path);
					Console.WriteLine("  JSON : {0}  ({1} bytes)", fileName, len);
					Console.WriteLine("  明文 : {0}", Path.GetFileName(txtPath));
					Console.WriteLine("---------- 明文开始 ----------");
					SetupSheetOps.PrintPlainText(sheet);
					Console.WriteLine("---------- 明文结束 ----------");
					Console.Write("> ");
				}
				else
				{
					Console.WriteLine();
					Console.WriteLine("[{0:HH:mm:ss}] POST {1} -> JSON 已落盘,但对象还原失败", DateTime.Now, path);
					Console.WriteLine("  保存: {0}  ({1} bytes)", fileName, len);
					Console.WriteLine("  原因: {0}", deserializeError);
					Console.Write("> ");
				}

				if (_forceFail)
				{
					WriteText(response, 500, "application/json; charset=utf-8",
						"{\"success\":false,\"message\":\"demo forced failure (--fail)\"}");
					return;
				}

				const string okJson = "{\"success\":true,\"message\":\"received\"}";
				WriteText(response, 200, "application/json; charset=utf-8", okJson);
			}
			catch (Exception ex)
			{
				try
				{
					WriteText(response, 500, "text/plain; charset=utf-8", "Error: " + ex.Message);
				}
				catch { }
				Console.WriteLine("[{0:HH:mm:ss}] ERROR: {1}", DateTime.Now, ex.Message);
			}
			finally
			{
				try { response.OutputStream.Close(); } catch { }
			}
		}

		private static void WriteText(HttpListenerResponse response, int statusCode, string contentType, string text)
		{
			byte[] buffer = Encoding.UTF8.GetBytes(text ?? string.Empty);
			response.StatusCode = statusCode;
			response.ContentType = contentType;
			response.ContentEncoding = Encoding.UTF8;
			response.ContentLength64 = buffer.Length;
			response.OutputStream.Write(buffer, 0, buffer.Length);
		}
	}
}


Models/SetupsheetModels.cs

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace JmSetupSheetReceiver.Models
{
	/// <summary>
	/// 程序单对外 POST JSON 的根对象。
	/// </summary>
	public class SetupsheetData
	{
		/// <summary>串联坐标名称</summary>
		public string NcWpName { get; set; }

		/// <summary>项目数据</summary>
		public ProjectData ProjectData { get; set; }

		/// <summary>精公火花位</summary>
		public double ThicknessF { get; set; }

		/// <summary>中公火花位</summary>
		public double ThicknessM { get; set; }

		/// <summary>粗公火花位</summary>
		public double ThicknessR { get; set; }

		/// <summary>精公数量</summary>
		public int NumberF { get; set; }

		/// <summary>中公数量</summary>
		public int NumberM { get; set; }

		/// <summary>粗公数量</summary>
		public int NumberR { get; set; }

		/// <summary>精公自动换刀 NC 名称</summary>
		public string AutoToolChangNcF { get; set; }

		/// <summary>中公自动换刀 NC 名称</summary>
		public string AutoToolChangNcM { get; set; }

		/// <summary>粗公自动换刀 NC 名称</summary>
		public string AutoToolChangNcR { get; set; }

		/// <summary>电极头检测尺寸</summary>
		public string DetectionSize { get; set; }

		/// <summary>电极基准面 Z 值</summary>
		public double ReferencePlaneZval { get; set; }

		/// <summary>程序单生成时间</summary>
		public string CreatTime { get; set; }

		/// <summary>工件号(或工件数量相关标识,以实际报文为准)</summary>
		public string PieceNumber { get; set; }

		/// <summary>工位列表</summary>
		public List<PositionData> PositionDataList { get; set; }

		/// <summary>精公二维码</summary>
		public string CellBarCodeF { get; set; }

		/// <summary>中公二维码</summary>
		public string CellBarCodeM { get; set; }

		/// <summary>粗公二维码</summary>
		public string CellBarCodeR { get; set; }

		/// <summary>工件分中 Z 轴取数方式</summary>
		public string ZType { get; set; }

		/// <summary>NC 串联是否旋转工件</summary>
		public bool NcRotate { get; set; }

		/// <summary>NC 串联工件旋转角度</summary>
		public double NcAngle { get; set; }

		/// <summary>NC 串联是否镜像工件</summary>
		public bool NcMirror { get; set; }

		/// <summary>NC 串联镜像参考平面:0=YZ 平面;1=XZ 平面</summary>
		public int NcAxis { get; set; }

		/// <summary>未知或新增字段保留于此,避免丢数据</summary>
		[JsonExtensionData]
		public IDictionary<string, JToken> ExtensionData { get; set; }

		/// <summary>工位数量(计算属性,不参与 JSON)</summary>
		[JsonIgnore]
		public int PositionCount
		{
			get { return PositionDataList == null ? 0 : PositionDataList.Count; }
		}

		/// <summary>遍历全部工位下的刀路</summary>
		public IEnumerable<ToolPathData> EnumerateToolPaths()
		{
			if (PositionDataList == null) yield break;
			foreach (var pos in PositionDataList)
			{
				if (pos == null || pos.ToolPathList == null) continue;
				foreach (var tp in pos.ToolPathList)
				{
					if (tp != null) yield return tp;
				}
			}
		}
	}

	/// <summary>项目数据</summary>
	public class ProjectData
	{
		/// <summary>不考虑工件数量的项目总时长(一般不使用)</summary>
		public TimeSpan PDTotalTime { get; set; }

		/// <summary>不考虑工件数量的项目切削移动时长(一般不使用)</summary>
		public TimeSpan PDCutTime { get; set; }

		/// <summary>项目总时长</summary>
		public TimeSpan TotalTime { get; set; }

		/// <summary>项目切削移动时长</summary>
		public TimeSpan CutTime { get; set; }

		/// <summary>项目路径</summary>
		public string PDSession { get; set; }

		/// <summary>NC 输出路径</summary>
		public string NcprogramPath { get; set; }

		/// <summary>项目名称</summary>
		public string Project { get; set; }

		/// <summary>未知或新增字段</summary>
		[JsonExtensionData]
		public IDictionary<string, JToken> ExtensionData { get; set; }
	}

	/// <summary>工位数据</summary>
	public class PositionData
	{
		/// <summary>当前工位刀路列表</summary>
		public List<ToolPathData> ToolPathList { get; set; }

		/// <summary>当前毛坯最大 Z 值</summary>
		public double StartBlockMaxZ { get; set; }

		/// <summary>当前工位名称</summary>
		public string PositionName { get; set; }

		/// <summary>当前工位模型尺寸</summary>
		public EntitySize ModelSizeByPosition { get; set; }

		/// <summary>当前工位毛料尺寸</summary>
		public EntitySize BlockSizeByPosition { get; set; }

		/// <summary>工位总时长</summary>
		public TimeSpan PositionTotalTime { get; set; }

		/// <summary>工位切削移动时长</summary>
		public TimeSpan PositionCutTime { get; set; }

		/// <summary>工位视图图片(JSON 中多为 Base64,还原后为字节数组)</summary>
		public List<byte[]> ImageBytesList { get; set; }

		/// <summary>基准角位置:0 左上角;1 左下角;2 右上角;3 右下角</summary>
		public int DatumMark { get; set; }

		/// <summary>订料尺寸字符串,如 25*25*20</summary>
		public string BlockSizeString { get; set; }

		/// <summary>工位界面配置快照(客户、机床、材质等)</summary>
		public ConfigSetupSheet ConfigSetupSheet { get; set; }

		/// <summary>未知或新增字段</summary>
		[JsonExtensionData]
		public IDictionary<string, JToken> ExtensionData { get; set; }

		/// <summary>刀路数量(计算属性,不参与 JSON)</summary>
		[JsonIgnore]
		public int ToolPathCount
		{
			get { return ToolPathList == null ? 0 : ToolPathList.Count; }
		}
	}

	/// <summary>包围盒(模型 / 毛料 / 刀路尺寸)</summary>
	public class EntitySize
	{
		/// <summary>X 最小</summary>
		public double Xmin { get; set; }

		/// <summary>X 最大</summary>
		public double Xmax { get; set; }

		/// <summary>Y 最小</summary>
		public double Ymin { get; set; }

		/// <summary>Y 最大</summary>
		public double Ymax { get; set; }

		/// <summary>Z 最小</summary>
		public double Zmin { get; set; }

		/// <summary>Z 最大</summary>
		public double Zmax { get; set; }

		public override string ToString()
		{
			return string.Format("X[{0:0.###},{1:0.###}] Y[{2:0.###},{3:0.###}] Z[{4:0.###},{5:0.###}]",
				Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
		}
	}

	/// <summary>工位界面配置快照(常用字段;其余进 ExtensionData)</summary>
	public class ConfigSetupSheet
	{
		/// <summary>客户名称</summary>
		public string Customers { get; set; }

		/// <summary>机床编号</summary>
		public string MachineNo { get; set; }

		/// <summary>材质</summary>
		public string Material { get; set; }

		/// <summary>模号</summary>
		public string MouldNo { get; set; }

		/// <summary>工件名称</summary>
		public string PieceName { get; set; }

		/// <summary>员工姓名</summary>
		public string EmployeeName { get; set; }

		/// <summary>装夹方式</summary>
		public string ClampType { get; set; }

		/// <summary>Excel 相关配置标识</summary>
		public string Excel { get; set; }

		/// <summary>Html 相关配置标识</summary>
		public string Html { get; set; }

		/// <summary>工作平面相关配置</summary>
		public string YnWorkplane { get; set; }

		/// <summary>分中类型默认值</summary>
		public string CenterTypeDefault_Value { get; set; }

		/// <summary>其余配置字段</summary>
		[JsonExtensionData]
		public IDictionary<string, JToken> ExtensionData { get; set; }
	}

	/// <summary>刀路数据</summary>
	public class ToolPathData
	{
		/// <summary>串联坐标名称</summary>
		public string NcWpName { get; set; }

		/// <summary>NC 名称</summary>
		public string Ncprogram { get; set; }

		/// <summary>刀路名称</summary>
		public string Toolpath { get; set; }

		/// <summary>刀具名称</summary>
		public string ToolID { get; set; }

		/// <summary>刀尖类型</summary>
		public string ToolType { get; set; }

		/// <summary>刀具直径</summary>
		public double Dia { get; set; }

		/// <summary>刀尖圆角</summary>
		public double Tip { get; set; }

		/// <summary>刀具伸出长度</summary>
		public double Overhang { get; set; }

		/// <summary>刀路 Z 最小值</summary>
		public double TPZMin { get; set; }

		/// <summary>旧版转速(停用)</summary>
		public double Spindle { get; set; }

		/// <summary>旧版进给(停用)</summary>
		public double Cut { get; set; }

		/// <summary>公差</summary>
		public double Tol { get; set; }

		/// <summary>总时间</summary>
		public TimeSpan Totaltime { get; set; }

		/// <summary>切削时间</summary>
		public TimeSpan CutTime { get; set; }

		/// <summary>径向余量</summary>
		public double Thickness { get; set; }

		/// <summary>轴向余量</summary>
		public double AxialThickness { get; set; }

		/// <summary>是否碰撞检测</summary>
		public bool CollChecked { get; set; }

		/// <summary>刀号</summary>
		public string ToolNumber { get; set; }

		/// <summary>NC 描述</summary>
		public string Description { get; set; }

		/// <summary>刃长</summary>
		public double Len { get; set; }

		/// <summary>锥度直径</summary>
		public double TaperDiameter { get; set; }

		/// <summary>刀具锥度</summary>
		public double TaperAngle { get; set; }

		/// <summary>行距</summary>
		public double Stepover { get; set; }

		/// <summary>步距</summary>
		public double Stepdown { get; set; }

		/// <summary>NC 备注</summary>
		public string NcprogramNotes { get; set; }

		/// <summary>刀具描述</summary>
		public string ToolDescription { get; set; }

		/// <summary>进给(快速相关)</summary>
		public double FeedRateRapid { get; set; }

		/// <summary>刀头最大</summary>
		public double THUpper { get; set; }

		/// <summary>刀柄最大</summary>
		public double TSUpper { get; set; }

		/// <summary>刀头最小</summary>
		public double THLower { get; set; }

		/// <summary>刀柄最小</summary>
		public double TSLower { get; set; }

		/// <summary>刀路坐标</summary>
		public string WKPLName { get; set; }

		/// <summary>刀头名称</summary>
		public string HolderName { get; set; }

		/// <summary>刀具格式后名称</summary>
		public string Tool { get; set; }

		/// <summary>刀具备注</summary>
		public string ToolNote { get; set; }

		/// <summary>加工深度(模型最高 Z 与刀路最小 Z 之差)</summary>
		public double Depth { get; set; }

		/// <summary>刀路备注</summary>
		public string ToolpathNotes { get; set; }

		/// <summary>刀头几何列表</summary>
		public List<HolderOrShank> ToolHolders { get; set; }

		/// <summary>刀柄几何列表</summary>
		public List<HolderOrShank> ToolShanks { get; set; }

		/// <summary>NC 路径</summary>
		public string NcprogramPath { get; set; }

		/// <summary>圆角盘铣刀刀具上圆角</summary>
		public double UpperTip { get; set; }

		/// <summary>刀柄名称</summary>
		public string ShankName { get; set; }

		/// <summary>加长杆名称</summary>
		public string ExtensionName { get; set; }

		/// <summary>加长杆长度</summary>
		public double ExtensionLength { get; set; }

		/// <summary>刀柄长度</summary>
		public double ShankLength { get; set; }

		/// <summary>刀头加长杆刀柄</summary>
		public string HolderExtensioShank { get; set; }

		/// <summary>刀头加长杆</summary>
		public string HolderExtensio { get; set; }

		/// <summary>安全高度</summary>
		public double SafeZ { get; set; }

		/// <summary>半径补偿编码</summary>
		public int CompCode { get; set; }

		/// <summary>启用半径补偿</summary>
		public bool RadiusCompNumber_Active { get; set; }

		/// <summary>半径补偿号</summary>
		public int RadiusCompNumber_Value { get; set; }

		/// <summary>夹持名称</summary>
		public string OldHolderName { get; set; }

		/// <summary>刀具半径补偿</summary>
		public bool CncCutterCompensationActive { get; set; }

		/// <summary>NC 文件大小</summary>
		public string NcFileSize { get; set; }

		/// <summary>NC 输出坐标系</summary>
		public string NcWorkplane { get; set; }

		/// <summary>切削长度</summary>
		public double CutLength { get; set; }

		/// <summary>标题</summary>
		public string Title { get; set; }

		/// <summary>刀具寿命</summary>
		public double ToolLife { get; set; }

		/// <summary>刀路 X 最大值</summary>
		public double TPXmax { get; set; }

		/// <summary>刀路 X 最小值</summary>
		public double TPXmin { get; set; }

		/// <summary>刀路 Y 最大值</summary>
		public double TPYmax { get; set; }

		/// <summary>刀路 Y 最小值</summary>
		public double TPYmin { get; set; }

		/// <summary>刀路 Z 最大值</summary>
		public double TPZmax { get; set; }

		/// <summary>刀路 Z 最小值</summary>
		public double TPZmin { get; set; }

		/// <summary>刀路尺寸列表</summary>
		public List<EntitySize> TpSizeList { get; set; }

		/// <summary>标距长度</summary>
		public double GaugeLength { get; set; }

		/// <summary>策略类型</summary>
		public string Strategy { get; set; }

		/// <summary>钻孔径向余量</summary>
		public double DrillThickness { get; set; }

		/// <summary>钻孔轴向余量</summary>
		public double DrillAxialThickness { get; set; }

		/// <summary>径向余量(刀路)</summary>
		public double TpThickness { get; set; }

		/// <summary>轴向余量(刀路)</summary>
		public double TpAxialThickness { get; set; }

		/// <summary>钻孔深度类型</summary>
		public string DrillDepthType { get; set; }

		/// <summary>钻孔深度是否用户定义</summary>
		public string DrillDepthUserDefined { get; set; }

		/// <summary>刀具切削安全状态</summary>
		public string SafetyToolCuttingStatus { get; set; }

		/// <summary>刀具切入切出安全状态</summary>
		public string SafetyToolLeadsStatus { get; set; }

		/// <summary>刀具连接安全状态</summary>
		public string SafetyToolLinksStatus { get; set; }

		/// <summary>刀头切削安全状态</summary>
		public string SafetyHolderCuttingStatus { get; set; }

		/// <summary>刀头切入切出安全状态</summary>
		public string SafetyHolderLeadsStatus { get; set; }

		/// <summary>刀头连接安全状态</summary>
		public string SafetyHolderLinksStatus { get; set; }

		/// <summary>串联二维码</summary>
		public List<string> NcCodeList { get; set; }

		/// <summary>转速</summary>
		public string Rpm { get; set; }

		/// <summary>进给</summary>
		public string Frate { get; set; }

		/// <summary>钻孔循环类型</summary>
		public string DrillType { get; set; }

		/// <summary>钻孔啄孔深度</summary>
		public string PeckDepth { get; set; }

		/// <summary>标记为单独刀具、不合并 NC 的瞬态标志</summary>
		public bool NoMerge { get; set; }

		/// <summary>未知或新增字段</summary>
		[JsonExtensionData]
		public IDictionary<string, JToken> ExtensionData { get; set; }

		public override string ToString()
		{
			return string.Format("{0} | 刀 {1} Dia={2} | NC={3}",
				Toolpath ?? "(unnamed)",
				ToolID ?? Tool ?? "?",
				Dia,
				Ncprogram ?? "");
		}
	}

	/// <summary>刀头 / 刀柄几何段</summary>
	public class HolderOrShank
	{
		/// <summary>上直径</summary>
		public double UpperDiameter { get; set; }

		/// <summary>下直径</summary>
		public double LowerDiameter { get; set; }

		/// <summary>长度</summary>
		public double Length { get; set; }
	}
}


相关页面:接收端演示与联调 · 程序单数据对接 · 字段参考