using Common; using Common.HTTPModels; using Common.Models; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using Dm.filter.log; using MegaRobo.C00225155.Entities.Enums; using MegaRobo.C00225155.Entities.FromWeb; using MegaRobo.C00225155.Entities.FromWeb.Test; using MegaRobo.Connections.Web; using MegaRobo.Contract.Servers; using MegaRobo.ControlDevices.Abstractions; using MegaRobo.Entities; using MegaRobo.Logger; using MegaRobo.PipetteTool.HamiltonConsole; using NetTaste; using Newtonsoft.Json; using SqlSugar; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using System.Windows.Interop; using static System.Net.Mime.MediaTypeNames; namespace MegaRobo.C00225155.AppServer { public partial class WorkService { #region 和BS交互触发事件 public event EventHandler PrepareUploadBox; public event EventHandler UpdateBoxInfo_BS; #endregion private HttpListenerService _httpListenerService; #region 监听接口路由 private readonly string _testName = "/api/v1/test"; private readonly string _testName1 = "/device/A1/test"; #endregion #region 增加swagger private readonly List _registeredApis = new(); private class ApiRouteInfo { public string Path { get; set; } public string HttpMethod { get; set; } = "POST"; public string Summary { get; set; } public Type RequestType { get; set; } // 可选,用于生成 schema } private void AddSwaggerSupport() { _httpListenerService.AddRoute("swagger", async msg => { if (msg.HttpMethod == "GET") { const string html = @" 设备控制 API - Swagger
"; msg.Response.Headers["Content-Type"] = "text/html; charset=utf-8"; await msg.ReplyAsync(html); } }); _httpListenerService.AddRoute("swagger/v1/swagger.json", async msg => { if (msg.HttpMethod == "GET") { var openApi = GenerateOpenApiSpec(); await msg.ReplyAsync(openApi); } }); } private string GenerateOpenApiSpec() { var baseUrl = "http://localhost"; var port = 10001; var paths = new Dictionary(); foreach (var api in _registeredApis) { var operation = new Dictionary { ["summary"] = api.Summary, ["responses"] = new Dictionary { ["200"] = new Dictionary { ["description"] = "成功" } } }; if (api.HttpMethod == "POST" && api.RequestType != null) { var schema = BuildInlineSchema(api.RequestType); // 👈 关键:内联生成 schema operation["requestBody"] = new Dictionary { ["required"] = true, ["content"] = new Dictionary { ["application/json"] = new Dictionary { ["schema"] = schema } } }; } paths[api.Path] = new Dictionary { [api.HttpMethod.ToLower()] = operation }; } var openApi = new Dictionary { ["openapi"] = "3.0.3", ["info"] = new Dictionary { ["title"] = "MegaRobo 设备控制 API", ["version"] = "v1" }, ["servers"] = new[] { new Dictionary { ["url"] = $"{baseUrl}:{port}" }}, ["paths"] = paths }; return JsonConvert.SerializeObject(openApi, Formatting.Indented); } private object BuildInlineSchema(Type type) { // 如果是简单类型(string/int/bool等),直接返回类型 if (IsSimpleType(type)) { return new Dictionary { ["type"] = MapDotNetTypeToOpenApi(type) }; } // 枚举:统一视为 string if (type.IsEnum) { return new Dictionary { ["type"] = "string" }; } // 集合类型(List, ObservableCollection 等) if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type) && type != typeof(string)) { return new Dictionary { ["type"] = "array", ["items"] = new Dictionary { ["type"] = "object" } // 不展开元素类型 }; } // 对象类型:只取自身 + 基类(直到 ObservableObject 之前) var properties = new Dictionary(); var current = type; while (current != null && current != typeof(object)) { // 遇到 ObservableObject 就停止 if (current == typeof(ObservableObject) || (typeof(ObservableObject).IsAssignableFrom(current) && current != type)) { break; } // 只取当前层级声明的 public 实例属性 foreach (var prop in current.GetProperties( System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly)) { if (!prop.CanRead) continue; var propType = prop.PropertyType; // 处理 Nullable if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable<>)) { propType = Nullable.GetUnderlyingType(propType); } if (propType == null) continue; // 枚举 → string 改为 integer if (propType.IsEnum) { properties[prop.Name] = new Dictionary { ["type"] = "integer" }; } // 集合 → array of object else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(propType) && propType != typeof(string)) { properties[prop.Name] = new Dictionary { ["type"] = "array", ["items"] = new Dictionary { ["type"] = "object" } }; } // 简单类型 else if (IsSimpleType(propType)) { properties[prop.Name] = new Dictionary { ["type"] = MapDotNetTypeToOpenApi(propType) }; } // 其他复杂对象 → 统一视为 object(不展开) else { properties[prop.Name] = new Dictionary { ["type"] = "object" }; } } current = current.BaseType; } return new Dictionary { ["type"] = "object", ["properties"] = properties }; } private string MapDotNetTypeToOpenApi(Type type) { if (type == typeof(string)) return "string"; if (type == typeof(int) || type == typeof(long)) return "integer"; if (type == typeof(float) || type == typeof(double) || type == typeof(decimal)) return "number"; if (type == typeof(bool)) return "boolean"; if (type == typeof(DateTime) || type == typeof(DateTimeOffset)) return "string"; // OpenAPI 用 string 表示时间 if (type == typeof(Guid)) return "string"; return "string"; } private bool IsSimpleType(Type type) { if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime) || type == typeof(DateTimeOffset) || type == typeof(Guid) || type == typeof(decimal)) return true; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) return IsSimpleType(Nullable.GetUnderlyingType(type)); return false; } #endregion /// /// 将特定的 HTTP 路径(路由)与对应的处理方法关联 /// HttpListenerService 能够监听这些路径的请求并执行对应的业务逻辑 /// 当传入 deviceKey = "A5" 时,会生成路由: /// 测试接口:/api/v1/test → 绑定 OnTest 方法,用于测试接口可用性,返回调用成功的 JSON 响应。 /// 设备同步序列接口:/device/A5/sync-seq → 绑定 SyncSeq 方法(目前方法体为空,可后续扩展同步设备序列的逻辑)。 /// /// private void RegiondRoute(string deviceKey) { // 清空旧记录(防止重复) _registeredApis.Clear(); string _info = $"/device/{deviceKey}/info"; string _isAllow = $"/device/{deviceKey}/is-allow"; string _get_storage = $"/device/{deviceKey}/get-storage"; string _open_door = $"/device/{deviceKey}/open-door"; string _load = $"/device/{deviceKey}/load"; string _unload = $"/device/{deviceKey}/unload"; string _sync_seq = $"/device/{deviceKey}/sync-seq"; string _add_seq = $"/device/{deviceKey}/add-seq"; string _delete_seq = $"/device/{deviceKey}/delete-seq"; string _control = $"/device/{deviceKey}/control"; //添加监听接口路由 this._httpListenerService.AddRoute(this._testName, this.OnTest); this._httpListenerService.AddRoute(this._testName1, this.OnTest1); this._httpListenerService.AddRoute(_info, this.MachineInfo); this._httpListenerService.AddRoute(_isAllow, this.IsAllowOperate); this._httpListenerService.AddRoute(_get_storage, this.GetStorage); this._httpListenerService.AddRoute(_open_door, this.OpenDoor); this._httpListenerService.AddRoute(_load, this.LoadConsumable); this._httpListenerService.AddRoute(_unload, this.UnLoad); this._httpListenerService.AddRoute(_sync_seq, this.SyncSeqEx); this._httpListenerService.AddRoute(_add_seq, this.AddSeq); this._httpListenerService.AddRoute(_delete_seq, this.DeleteSeq); this._httpListenerService.AddRoute(_control, this.MachineControl); // 记录元数据(用于 Swagger) _registeredApis.Add(new ApiRouteInfo { Path = _testName, HttpMethod = "GET", Summary = "测试接口" }); _registeredApis.Add(new ApiRouteInfo { Path = _info, HttpMethod = "GET", Summary = "查询机台状态信息" }); _registeredApis.Add(new ApiRouteInfo { Path = _isAllow, HttpMethod = "GET", Summary = "是否允许上料" }); _registeredApis.Add(new ApiRouteInfo { Path = _get_storage, HttpMethod = "GET", Summary = "获取机台可以放置的物料信息" }); _registeredApis.Add(new ApiRouteInfo { Path = _open_door, HttpMethod = "GET", Summary = "打开舱门,准备上料" }); _registeredApis.Add(new ApiRouteInfo { Path = _load, HttpMethod = "POST", Summary = "开始上料", RequestType = typeof(List) }); _registeredApis.Add(new ApiRouteInfo { Path = _unload, HttpMethod = "POST", Summary = "下料完成", RequestType = typeof(UnLoadModel) }); _registeredApis.Add(new ApiRouteInfo { Path = _sync_seq, HttpMethod = "POST", Summary = "同步样品序列", RequestType = typeof(List) }); _registeredApis.Add(new ApiRouteInfo { Path = _add_seq, HttpMethod = "POST", Summary = "添加新序列", RequestType = typeof(List) }); _registeredApis.Add(new ApiRouteInfo { Path = _delete_seq, HttpMethod = "POST", Summary = "取消序列执行", RequestType = typeof(List) }); _registeredApis.Add(new ApiRouteInfo { Path = _control, HttpMethod = "POST", Summary = "机台控制指令", RequestType = typeof(ControlCmd) }); } /// /// 测试接口,为了给客户看而使用的接口,后期屏蔽 /// /// /// private async Task OnTest1(HttpListenerMessage msg) { Response result = new Response(); string str = msg.GetMessageString(); //如果是post则接受数据并反序列化 //string str = await msg.GetRequestBodyStringAsync(); //如果是post则接受数据并反序列化 result.code = 0; result.msg = $"{_testName} 接口调用成功"; result.data = true; if (stationService_Dose.StationProp.deviceStatus != Entities.DeviceStatus.Idel) { result.code = 1; result.msg = $"{_testName} 接口调用失败,设备不在安全状态"; Logger.LogInformation($"{_testName} 接口调用失败,设备不在安全状态"); await msg.ReplyAsync(result.ToJson()); return; } await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"向BS发送完成接收到-Test1请求,返回成功"); _ = Task.Run(async() => { //导入方案 ProjectPro.bNoUseBS = true; #region ProjectProperty project = new ProjectProperty(); bool readOk = false; project = File_Operator.Xml_Serialize("C:\\Users\\CTOS\\Desktop\\测试流程_1.pro", false, project, out readOk); if (readOk) { ProjectPro = project; ProjectPro.LastOpenProject = "C:\\Users\\CTOS\\Desktop\\测试流程_1.pro"; ProjectPro.NowOpenProjectFile = "C:\\Users\\CTOS\\Desktop\\测试流程_1.pro".Substring("C:\\Users\\CTOS\\Desktop\\测试流程_1.pro".LastIndexOf("\\") + 1).Trim(); WeakReferenceMessenger.Default.Send(new DesktopAlertMessage { Content = "打开项目文件成功!" }); } #endregion await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.CarryOn); await stationService_Dose.StartLoad(); await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.Runing); }); } private async Task OnTest(HttpListenerMessage msg) { Response result = new Response(); string str = msg.GetMessageString(); //如果是post则接受数据并反序列化 //string str = await msg.GetRequestBodyStringAsync(); //如果是post则接受数据并反序列化 result.code = 0; result.msg = $"{_testName} 接口调用成功"; await msg.ReplyAsync(result.ToJson()); } /// /// 机台信息查询 /// /// /// private async Task MachineInfo(HttpListenerMessage msg) { Logger.LogInformation($"{DateTime.Now}收到机台查询状态指令"); Response result = new Response(); result.code = 0; result.msg = $"{stationService_Dose.StationProp.deviceStatus.ToString()}"; var isInitOk = stationService_Dose.GetInitStatus(); if (isInitOk != 3) { stationService_Dose.StationProp.deviceStatus = Entities.DeviceStatus.Disable; } result.data = new { status = new { deviceStatus = stationService_Dose.StationProp.deviceStatus.ToString(), //isAllowLoad = true, //todo:测试先不做校验 isAllowLoad = this.stationService_Dose.StationProp.deviceStatus == Entities.DeviceStatus.Idel //这边可能需要扩展,CS要完全下料完成才能认为是Idel } }; string json = JsonConvert.SerializeObject(result); Logger.LogInformation($"{DateTime.Now}收到机台查询状态指令-返回{json}"); await msg.ReplyAsync(json); //var testJson = new { test = "测试" }; //var testres = await stationService_Dose.SendJson("111", "test_1", testJson.ToString()); } /// /// 机台信息查询 /// /// /// private async Task IsAllowOperate(HttpListenerMessage msg) { Response result = new Response(); result.code = 0; result.msg = $"操作成功"; Logger.LogInformation($"{DateTime.Now}收到机台查询允许上料指令"); bool res = this.stationService_Dose.StationProp.deviceStatus == Entities.DeviceStatus.Idel; result.data = res; string json = JsonConvert.SerializeObject(result); Logger.LogInformation($"{DateTime.Now}收到机台查询允许上料指令-返回{json}"); await msg.ReplyAsync(json); } private async Task GetStorage(HttpListenerMessage msg) { Response result = new Response(); result.code = 0; result.msg = $"操作成功"; Logger.LogInformation($"{DateTime.Now}收到机台查询库位指令"); //这边获取机台可以存放的40ml. 5/12ml tip 及 粉末头放置的个数 var _5or12_fixtures = ProjectPro.FixtureCacheArea.Count(b => (b.FixtureType == BoxTypeEnum._12mL样品工装 || b.FixtureType == BoxTypeEnum._5mL样品工装) && !b.IsEmpty); var _40_fixtures = ProjectPro.FixtureCacheArea.Count(b => b.FixtureType == BoxTypeEnum._40mL原液工装 && !b.IsEmpty); var _powderHeaders = ProjectPro.PowderHeaderCacheArea.Count(b => b.HaveBottle); var _tipFixtures = ProjectPro.TipHeadArea.Count(b => !b.IsEmpty); List transferPoss = new List(); for (int i = 0; i < ProjectPro.TransferArea.Count; i++) { if (ProjectPro.TransferArea[i].IsEmpty) { transferPoss.Add(i + 1); } } result.data = new { sampleFixtureRemainCount = 4 - _5or12_fixtures, sourceFixtureRemainCount = 2 - _40_fixtures, tipFixTureRemainCount = 3 - _tipFixtures, powderHeaderRemainCount = 10 - _powderHeaders, transferArea = transferPoss }; string json = JsonConvert.SerializeObject(result); Logger.LogInformation($"{DateTime.Now}收到机台查询库位指令-返回{json}"); await msg.ReplyAsync(json); } private async Task OpenDoor(HttpListenerMessage msg) { Response result = new Response(); result.code = 0; result.msg = $"操作成功"; Logger.LogInformation($"{DateTime.Now}收到机台开门指令"); if (this.stationService_Dose.StationProp.deviceStatus != Entities.DeviceStatus.Idel) { result.data = false; result.code = 1; result.msg = $"机台不在就绪状态,不能打开门"; var json = JsonConvert.SerializeObject(result); await msg.ReplyAsync(json); Logger.LogInformation($"{DateTime.Now}收到机台开门指令-返回{json}"); } else { await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.CarryOn); result.data = true; var json = JsonConvert.SerializeObject(result); Logger.LogInformation($"{DateTime.Now}收到机台开门指令-返回{json}"); await msg.ReplyAsync(json); _ = Task.Run(async () => { await stationService_Dose.OpenDoor(); }); } } /// /// 判断上料数据是否合法 /// /// /// private (bool isSuccess, string msg) ValidateUploadData(List uploadDatas) { (bool isSuccess, string msg) result = (true, ""); //规则(*):母液最多2-已使用个,目标最多4-已使用个,tip最多3-已使用个,粉末最多2-已使用个载具,10-已使用个粉头 var _5or12_fixtures = ProjectPro.FixtureCacheArea.Count(b => (b.FixtureType == BoxTypeEnum._12mL样品工装 || b.FixtureType == BoxTypeEnum._5mL样品工装) && !b.IsEmpty); var _40_fixtures = ProjectPro.FixtureCacheArea.Count(b => b.FixtureType == BoxTypeEnum._40mL原液工装 && !b.IsEmpty); var _powderHeaders = ProjectPro.PowderHeaderCacheArea.Count(b => b.HaveBottle); var _tipFixtures = ProjectPro.TipHeadArea.Count(b => !b.IsEmpty); var powderHeaderRemainCount = 10 - _powderHeaders; if (uploadDatas.Count(x => x.fixtureType == BoxTypeEnum._40mL原液工装) > (2 - _40_fixtures)) { result.isSuccess = false; result.msg += $"原液工装剩余{(2 - _40_fixtures)}个位置,本次上料无法满足\n"; } if (uploadDatas.Count(x => x.fixtureType == BoxTypeEnum._12mL样品工装 || x.fixtureType == BoxTypeEnum._5mL样品工装) > (4 - _5or12_fixtures)) { result.isSuccess = false; result.msg += $"样品瓶工装剩余{(4 - _5or12_fixtures)}个位置,本次上料无法满足\n"; } if (uploadDatas.Count(x => x.fixtureType == BoxTypeEnum._1000uLTip头工装 || x.fixtureType == BoxTypeEnum._300uLTip头工装 || x.fixtureType == BoxTypeEnum._50uLTip头工装) > (3 - _tipFixtures)) { result.isSuccess = false; result.msg += $"Tip工装剩余{(3 - _tipFixtures)}个位置,本次上料无法满足\n"; } var sum = uploadDatas .Where(u => u.fixtureType == BoxTypeEnum._16mL粉末瓶工装 || u.fixtureType == BoxTypeEnum._125mL粉末瓶工装) .Sum(u => u.sourcePowderBottles.Count()); if (sum > powderHeaderRemainCount) { result.isSuccess = false; result.msg += $"粉末剩余{powderHeaderRemainCount}个位置,本次上料无法满足\n"; } //规则1:上料数目有限制,tip(remainCount:1~96)、原液瓶(8个)、目标瓶(12个)、粉末头(2/4个)不能超过剩余数目 //规则2:粉末/tip只能放在6,7 原液只能放在4,5 目标瓶只能在1,2,3 foreach (var uploadData in uploadDatas) { switch (uploadData.fixtureType) { case BoxTypeEnum._40mL原液工装: #region 规则1:原液载具只能放在4,5号位置,里面的瓶子最多只有8个,且里面的位置只能是在1-8 if (uploadData.boxId_inDoseUpload != 4 && uploadData.boxId_inDoseUpload != 5) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}不能放在{uploadData.boxId_inDoseUpload},只能放在4或者5号位置\n"; } if (uploadData.sourceLiquidBottles == null) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}里面没有原液瓶子信息\n"; } else { if (uploadData.sourceLiquidBottles.Count > 8) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}数目为{uploadData.sourceLiquidBottles.Count},原液最多只能有8个瓶子\n"; } if (uploadData.sourceLiquidBottles.Any(s => s.PosId_InBox > 8 || s.PosId_InBox < 1)) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}里面瓶子的PosId_InBox字段存在不是1~8的异常数\n"; } } #endregion break; case BoxTypeEnum._12mL样品工装: case BoxTypeEnum._5mL样品工装: #region 规则2:样品瓶只能放在1~3,里面瓶子最多只能有12个,且里面的位置只能在1~12 if (uploadData.boxId_inDoseUpload != 1 && uploadData.boxId_inDoseUpload != 2 && uploadData.boxId_inDoseUpload != 3) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}不能放在{uploadData.boxId_inDoseUpload},只能放在1~3号位置\n"; } if (uploadData.sampleBottles == null) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}里面没有样品瓶\n"; } else { if (uploadData.sampleBottles.Count > 12) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}数目为{uploadData.sourceLiquidBottles.Count},样品载具最多只能有12个瓶子\n"; } if (uploadData.sampleBottles.Any(s => s.PosId_InBox > 12 || s.PosId_InBox < 1)) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}里面瓶子的PosId_InBox字段存在不是1~12的异常数\n"; } } #endregion break; case BoxTypeEnum._16mL粉末瓶工装: case BoxTypeEnum._125mL粉末瓶工装: #region 规则3:粉末瓶只能放在6-7,里面瓶子最多只能有2/4个,且里面的位置只能在1~2/4 if (uploadData.boxId_inDoseUpload != 6 && uploadData.boxId_inDoseUpload != 7) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}不能放在{uploadData.boxId_inDoseUpload},只能放在6~7号位置\n"; } if (uploadData.sourcePowderBottles == null) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}里面没有粉末瓶\n"; } else { var maxCount = uploadData.fixtureType == BoxTypeEnum._16mL粉末瓶工装 ? 4 : 2; if (uploadData.sourcePowderBottles.Count > maxCount) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}数目为{uploadData.sourceLiquidBottles.Count},{uploadData.fixtureType.ToString()}载具最多只能有{maxCount}个瓶子\n"; } if (uploadData.sourcePowderBottles.Any(s => s.PosId_InBox > maxCount || s.PosId_InBox < 1)) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}里面瓶子的PosId_InBox字段存在不是1~{maxCount}的异常数\n"; } } #endregion break; case BoxTypeEnum._50uLTip头工装: case BoxTypeEnum._300uLTip头工装: case BoxTypeEnum._1000uLTip头工装: #region 规则4:tip只能放在6-7,里面剩余个数需要1~96 if (uploadData.boxId_inDoseUpload != 6 && uploadData.boxId_inDoseUpload != 7) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}不能放在{uploadData.boxId_inDoseUpload},只能放在6~7号位置\n"; } if (uploadData.RemainCount > 96 || uploadData.RemainCount < 1) { result.isSuccess = false; result.msg += $"{uploadData.boxSNCode}里面tip剩余个数{uploadData.RemainCount},应该是1~96\n"; } #endregion break; default: break; } } return result; } private async Task StartLoad(HttpListenerMessage msg) { Response result = new Response(); result.code = 0; result.msg = $"load接口调用成功"; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,内容-{str}"); if (!string.IsNullOrEmpty(str)) { if (stationService_Dose.StationProp.deviceStatus != Entities.DeviceStatus.Idel) { result.data = false; result.code = 1; result.msg = "未在就绪状态不允许上料"; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); return; } var uploadDatas = JsonConvert.DeserializeObject>(str); var res = ValidateUploadData(uploadDatas); result.data = res.isSuccess; result.msg = res.msg; if (!res.isSuccess) { result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); return; } foreach (var uploadData in uploadDatas) { switch (uploadData.fixtureType) { case BoxTypeEnum._40mL原液工装: var sourceBox = new SourceLiquidBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourceLiquidBottleCollection = new ObservableCollection() }; for (int i = 0; i < 8; i++) { var sourceBottle = uploadData.sourceLiquidBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourceBottle == null) { sourceBottle = new SourceLiquidBottleModel(); sourceBottle.HaveBottle = false; sourceBottle.PosId_InBox = i + 1; sourceBox.SourceLiquidBottleCollection.Add(sourceBottle); } else { sourceBottle.HaveBottle = true; sourceBottle.BoxSNCode = sourceBox.BoxSNCode; sourceBox.SourceLiquidBottleCollection.Add(sourceBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourceBox.BoxId_inDoseUpload - 1] = sourceBox; }); break; case BoxTypeEnum._12mL样品工装: case BoxTypeEnum._5mL样品工装: var sampleBox = new SampleBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SampleBottleList = new ObservableCollection() }; for (int i = 0; i < 12; i++) { var sampleBottle = uploadData.sampleBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sampleBottle == null) { sampleBottle = new SampleBottleModel(); sampleBottle.HaveBottle = false; sampleBottle.PosId_InBox = i + 1; if (sampleBottle.MaterialDoseFlowList == null) { sampleBottle.MaterialDoseFlowList = new ObservableCollection(); } sampleBox.SampleBottleList.Add(sampleBottle); } else { sampleBottle.SampleBottleType = uploadData.fixtureType == BoxTypeEnum._12mL样品工装 ? SampleBottleTypeEnum._12mL : SampleBottleTypeEnum._5mL; sampleBottle.HaveBottle = true; sampleBottle.BoxSNCode = sampleBox.BoxSNCode; if (sampleBottle.MaterialDoseFlowList == null) { sampleBottle.MaterialDoseFlowList = new ObservableCollection(); } sampleBox.SampleBottleList.Add(sampleBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sampleBox.BoxId_inDoseUpload - 1] = sampleBox; }); break; case BoxTypeEnum._16mL粉末瓶工装: var sourcePowderBottleBoxModel = new SourcePowderBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourcePowderBottleCollection = new ObservableCollection() }; for (int i = 0; i < 4; i++) { var sourcePowderBottle = uploadData.sourcePowderBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourcePowderBottle == null) { sourcePowderBottle = new SourcePowderBottleModel(); sourcePowderBottle.PosId_InBox = i + 1; sourcePowderBottle.HaveBottle = false; sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._16mL; sourcePowderBottleBoxModel.SourcePowderBottleCollection.Add(sourcePowderBottle); } else { sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._16mL; sourcePowderBottle.HaveBottle = true; sourcePowderBottle.BoxSNCode = sourcePowderBottleBoxModel.BoxSNCode; sourcePowderBottleBoxModel.SourcePowderBottleCollection.Add(sourcePowderBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourcePowderBottleBoxModel.BoxId_inDoseUpload - 1] = sourcePowderBottleBoxModel; }); break; case BoxTypeEnum._125mL粉末瓶工装: var sourcePowderBottleBoxModel_125Ml = new SourcePowderBottleBoxModel_125ml() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourcePowderBottleCollection = new ObservableCollection() }; for (int i = 0; i < 2; i++) { var sourcePowderBottle = uploadData.sourcePowderBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourcePowderBottle == null) { sourcePowderBottle = new SourcePowderBottleModel(); sourcePowderBottle.PosId_InBox = i + 1; sourcePowderBottle.HaveBottle = false; sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._125mL; sourcePowderBottleBoxModel_125Ml.SourcePowderBottleCollection.Add(sourcePowderBottle); } else { sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._125mL; sourcePowderBottle.HaveBottle = true; sourcePowderBottle.BoxSNCode = sourcePowderBottleBoxModel_125Ml.BoxSNCode; sourcePowderBottleBoxModel_125Ml.SourcePowderBottleCollection.Add(sourcePowderBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourcePowderBottleBoxModel_125Ml.BoxId_inDoseUpload - 1] = sourcePowderBottleBoxModel_125Ml; }); break; case BoxTypeEnum._50uLTip头工装: case BoxTypeEnum._300uLTip头工装: case BoxTypeEnum._1000uLTip头工装: TipBoxModel tipBoxModel = new TipBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, UseIndex = 96 - uploadData.RemainCount + 1, TipItems = new ObservableCollection() }; tipBoxModel.TipType = uploadData.fixtureType == BoxTypeEnum._50uLTip头工装 ? TipTypeEnum._50UL : (uploadData.fixtureType == BoxTypeEnum._300uLTip头工装 ? TipTypeEnum._300UL : TipTypeEnum._1000UL); for (int i = 0; i < tipBoxModel.UseIndex - 1; i++) { tipBoxModel.TipItems.Add(new TipHeadItem() { IsAvailable = false, UseIndex = i + 1 }); } for (int i = tipBoxModel.UseIndex - 1; i < 96; i++) { tipBoxModel.TipItems.Add(new TipHeadItem() { IsAvailable = true, UseIndex = i + 1 }); } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[tipBoxModel.BoxId_inDoseUpload - 1] = tipBoxModel; }); break; default: break; } } await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.CarryOn); await msg.ReplyAsync(JsonConvert.SerializeObject(result)); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); _ = Task.Run(async () => { await stationService_Dose.StartLoad(); }); } else { result.data = false; result.msg = "数据异常"; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); return; } /* 测试数据 List list = new List(); UploadBoxModel uploadBoxModel = new UploadBoxModel() { boxId_inDoseUpload = 4, boxSNCode = "1", fixtureType = BoxTypeEnum._40mL原液工装, sourceLiquidBottles = new List() { new SourceLiquidBottleModel(){ PosId_InBox = 1, SNCode = "", SourceLiquidName = "水", OriginVolume = 40, RemainVolume = 40}, new SourceLiquidBottleModel(){ PosId_InBox = 2, SNCode = "", SourceLiquidName = "EC", OriginVolume = 38, RemainVolume = 38}, new SourceLiquidBottleModel(){ PosId_InBox = 3, SNCode = "", SourceLiquidName = "DEC", OriginVolume = 35, RemainVolume = 35}, new SourceLiquidBottleModel(){ PosId_InBox = 5, SNCode = "", SourceLiquidName = "DMF", OriginVolume = 37, RemainVolume = 37}, } }; list.Add(uploadBoxModel); UploadBoxModel uploadBoxModel2 = new UploadBoxModel() { boxId_inDoseUpload = 2, boxSNCode = "2", fixtureType = BoxTypeEnum._5mL样品工装, sampleBottles = new List() { new SampleBottleModel() { PosId_InBox = 1, SNCode = "", SampleContentName = "", MaterialDoseFlowList = new ObservableCollection() { new MaterialDoseFunctionFlow(){ FunctionFlowType = FunctionTypeEnum.加液体原料, UseMaterialName = "水", TargetVolume = 1000}, new MaterialDoseFunctionFlow(){ FunctionFlowType = FunctionTypeEnum.加液体原料, UseMaterialName = "EC", TargetVolume = 1000}, new MaterialDoseFunctionFlow(){ FunctionFlowType = FunctionTypeEnum.加固体原料, UseMaterialName = "P1", TargetVolume = 2}, } }, new SampleBottleModel() { PosId_InBox = 2, SNCode = "", SampleContentName = "", MaterialDoseFlowList = new ObservableCollection() { new MaterialDoseFunctionFlow(){ FunctionFlowType = FunctionTypeEnum.加固体原料, UseMaterialName = "P2", TargetVolume = 10}, new MaterialDoseFunctionFlow(){ FunctionFlowType = FunctionTypeEnum.加液体原料, UseMaterialName = "DMF", TargetVolume = 1000}, new MaterialDoseFunctionFlow(){ FunctionFlowType = FunctionTypeEnum.加液体原料, UseMaterialName = "EC", TargetVolume = 1000} } } } }; list.Add(uploadBoxModel2); UploadBoxModel uploadBoxModel3 = new UploadBoxModel() { boxId_inDoseUpload = 6, boxSNCode = "6", fixtureType = BoxTypeEnum._1000uLTip头工装, RemainCount = 90 }; list.Add(uploadBoxModel3); UploadBoxModel uploadBoxModel4 = new UploadBoxModel() { boxId_inDoseUpload = 7, boxSNCode = "7", fixtureType = BoxTypeEnum._16mL粉末瓶工装, sourcePowderBottles = new List() { new SourcePowderBottleModel(){ PosId_InBox = 1, SNCode = "", SourcePowderName = "P1", OriginWeight = 16, RemainWeight = 16 }, new SourcePowderBottleModel(){ PosId_InBox = 2, SNCode = "", SourcePowderName = "P2", OriginWeight = 16, RemainWeight = 16 }, } }; list.Add(uploadBoxModel4); var testjson = JsonConvert.SerializeObject(list.ToList()); */ } /// /// 上耗材 /// /// /// private async Task LoadConsumable(HttpListenerMessage msg) { Response result = new Response() { code = 0, data = true, msg = "" }; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台上料耗材指令,内容-{str}"); if (string.IsNullOrEmpty(str)) { result.data = false; result.msg = "参数不正确"; result.code = 1; await msg.ReplyAsync(result.ToJson()); return; } try { var consumBoxs = JsonConvert.DeserializeObject(str); List uploadDatas = new List(); foreach (var consumBox in consumBoxs.Consumable) { if ((BoxTypeEnum)consumBox.FixtureType != BoxTypeEnum._300uLTip头工装 && (BoxTypeEnum)consumBox.FixtureType != BoxTypeEnum._50uLTip头工装 && (BoxTypeEnum)consumBox.FixtureType != BoxTypeEnum._1000uLTip头工装 && (BoxTypeEnum)consumBox.FixtureType != BoxTypeEnum._40mL原液工装 && (BoxTypeEnum)consumBox.FixtureType != BoxTypeEnum._16mL粉末瓶工装 && (BoxTypeEnum)consumBox.FixtureType != BoxTypeEnum._125mL粉末瓶工装) { result.data = false; result.msg = $"耗材类型{consumBox.FixtureType}不正确!"; result.code = 1; await msg.ReplyAsync(result.ToJson()); return; } UploadBoxModel uploadBox = new UploadBoxModel() { fixtureType = (BoxTypeEnum)consumBox.FixtureType, boxSNCode = consumBox.SnCode, boxId_inDoseUpload = consumBox.PosInUpload, RemainCount = consumBox.RemainCount }; if (uploadBox.fixtureType == BoxTypeEnum._40mL原液工装) { uploadBox.sourceLiquidBottles = new List(); foreach (var tubeInfo in consumBox.Detail) { SourceLiquidBottleModel sourceLiquidBottleModel = new SourceLiquidBottleModel() { BoxSNCode = consumBox.SnCode, HaveBottle = true, OriginVolume = tubeInfo.RemainWeight, RemainVolume = tubeInfo.RemainWeight, PosId_InBox = int.Parse(tubeInfo.Pos),SourceLiquidName = tubeInfo.Code }; uploadBox.sourceLiquidBottles.Add(sourceLiquidBottleModel); } } else if (uploadBox.fixtureType == BoxTypeEnum._16mL粉末瓶工装 || uploadBox.fixtureType == BoxTypeEnum._125mL粉末瓶工装) { uploadBox.sourcePowderBottles = new List(); foreach (var tubeInfo in consumBox.Detail) { SourcePowderBottleModel sourceBottle = new SourcePowderBottleModel() { BoxSNCode = consumBox.SnCode, HaveBottle = true, OriginWeight = tubeInfo.RemainWeight, RemainWeight = tubeInfo.RemainWeight, PosId_InBox = int.Parse(tubeInfo.Pos), SourcePowderName = tubeInfo.Code }; uploadBox.sourcePowderBottles.Add(sourceBottle); } } uploadDatas.Add(uploadBox); } var res = ValidateUploadData(uploadDatas); result.data = res.isSuccess; result.msg = res.msg; if (!res.isSuccess) { result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); return; } foreach (var uploadData in uploadDatas) { switch (uploadData.fixtureType) { case BoxTypeEnum._40mL原液工装: var sourceBox = new SourceLiquidBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourceLiquidBottleCollection = new ObservableCollection() }; for (int i = 0; i < 8; i++) { var sourceBottle = uploadData.sourceLiquidBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourceBottle == null) { sourceBottle = new SourceLiquidBottleModel(); sourceBottle.HaveBottle = false; sourceBottle.PosId_InBox = i + 1; sourceBox.SourceLiquidBottleCollection.Add(sourceBottle); } else { sourceBottle.HaveBottle = true; sourceBottle.BoxSNCode = sourceBox.BoxSNCode; sourceBox.SourceLiquidBottleCollection.Add(sourceBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourceBox.BoxId_inDoseUpload - 1] = sourceBox; }); break; case BoxTypeEnum._12mL样品工装: case BoxTypeEnum._5mL样品工装: var sampleBox = new SampleBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SampleBottleList = new ObservableCollection() }; for (int i = 0; i < 12; i++) { var sampleBottle = uploadData.sampleBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sampleBottle == null) { sampleBottle = new SampleBottleModel(); sampleBottle.HaveBottle = false; sampleBottle.PosId_InBox = i + 1; if (sampleBottle.MaterialDoseFlowList == null) { sampleBottle.MaterialDoseFlowList = new ObservableCollection(); } sampleBox.SampleBottleList.Add(sampleBottle); } else { sampleBottle.SampleBottleType = uploadData.fixtureType == BoxTypeEnum._12mL样品工装 ? SampleBottleTypeEnum._12mL : SampleBottleTypeEnum._5mL; sampleBottle.HaveBottle = true; sampleBottle.BoxSNCode = sampleBox.BoxSNCode; if (sampleBottle.MaterialDoseFlowList == null) { sampleBottle.MaterialDoseFlowList = new ObservableCollection(); } sampleBox.SampleBottleList.Add(sampleBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sampleBox.BoxId_inDoseUpload - 1] = sampleBox; }); break; case BoxTypeEnum._16mL粉末瓶工装: var sourcePowderBottleBoxModel = new SourcePowderBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourcePowderBottleCollection = new ObservableCollection() }; for (int i = 0; i < 4; i++) { var sourcePowderBottle = uploadData.sourcePowderBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourcePowderBottle == null) { sourcePowderBottle = new SourcePowderBottleModel(); sourcePowderBottle.PosId_InBox = i + 1; sourcePowderBottle.HaveBottle = false; sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._16mL; sourcePowderBottleBoxModel.SourcePowderBottleCollection.Add(sourcePowderBottle); } else { sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._16mL; sourcePowderBottle.HaveBottle = true; sourcePowderBottle.BoxSNCode = sourcePowderBottleBoxModel.BoxSNCode; sourcePowderBottleBoxModel.SourcePowderBottleCollection.Add(sourcePowderBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourcePowderBottleBoxModel.BoxId_inDoseUpload - 1] = sourcePowderBottleBoxModel; }); break; case BoxTypeEnum._125mL粉末瓶工装: var sourcePowderBottleBoxModel_125Ml = new SourcePowderBottleBoxModel_125ml() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourcePowderBottleCollection = new ObservableCollection() }; for (int i = 0; i < 2; i++) { var sourcePowderBottle = uploadData.sourcePowderBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourcePowderBottle == null) { sourcePowderBottle = new SourcePowderBottleModel(); sourcePowderBottle.PosId_InBox = i + 1; sourcePowderBottle.HaveBottle = false; sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._125mL; sourcePowderBottleBoxModel_125Ml.SourcePowderBottleCollection.Add(sourcePowderBottle); } else { sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._125mL; sourcePowderBottle.HaveBottle = true; sourcePowderBottle.BoxSNCode = sourcePowderBottleBoxModel_125Ml.BoxSNCode; sourcePowderBottleBoxModel_125Ml.SourcePowderBottleCollection.Add(sourcePowderBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourcePowderBottleBoxModel_125Ml.BoxId_inDoseUpload - 1] = sourcePowderBottleBoxModel_125Ml; }); break; case BoxTypeEnum._50uLTip头工装: case BoxTypeEnum._300uLTip头工装: case BoxTypeEnum._1000uLTip头工装: TipBoxModel tipBoxModel = new TipBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, UseIndex = 96 - uploadData.RemainCount + 1, TipItems = new ObservableCollection() }; tipBoxModel.TipType = uploadData.fixtureType == BoxTypeEnum._50uLTip头工装 ? TipTypeEnum._50UL : (uploadData.fixtureType == BoxTypeEnum._300uLTip头工装 ? TipTypeEnum._300UL : TipTypeEnum._1000UL); for (int i = 0; i < tipBoxModel.UseIndex - 1; i++) { tipBoxModel.TipItems.Add(new TipHeadItem() { IsAvailable = false, UseIndex = i + 1 }); } for (int i = tipBoxModel.UseIndex - 1; i < 96; i++) { tipBoxModel.TipItems.Add(new TipHeadItem() { IsAvailable = true, UseIndex = i + 1 }); } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[tipBoxModel.BoxId_inDoseUpload - 1] = tipBoxModel; }); break; default: break; } } } catch (Exception ex) { result.data = false; result.msg = ex.Message; result.code = 1; await msg.ReplyAsync(result.ToJson()); return; } await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); } private async Task UnLoad(HttpListenerMessage msg) { Response result = new Response() { code = 0, data = true, msg = "" }; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台下料完成指令,内容-{str}"); bool isCloseDoor = true; bool isBSRequest = true; List sourcePowderBottleBoxModels = null; if (!string.IsNullOrEmpty(str)) { try { var unLoadData = JsonConvert.DeserializeObject(str); sourcePowderBottleBoxModels = unLoadData.sourcePowderBottleBoxModel; isCloseDoor = !unLoadData.isContinueLoad; isBSRequest = unLoadData.isBSRequest; } catch (Exception ex) { result.data = false; result.msg = ex.Message; result.code = 1; await msg.ReplyAsync(result.ToJson()); return; } } else { result.data = false; result.msg = "参数不正确"; result.code = 1; await msg.ReplyAsync(result.ToJson()); return; } for (int i = 0; i < 7; i++) { App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[i] = new BaseBottleBox() { IsEmpty = true, BoxId_inDoseDnload = i + 1, BoxId_inDoseUpload = i + 1, IsDoseFinish = false, IsUseFinsh = false, BoxArea = BoxAreaEnum._手套箱传送平台 }; }); } if (sourcePowderBottleBoxModels != null) { var powderlist = new ObservableCollection(); for (int i = 0; i < 4; i++) { powderlist.Add(new SourcePowderBottleModel() { PosId_InBox = i + 1, HaveBottle = false, RemainWeight = 0, SNCode = string.Empty, PowderBottleType = PowderBottleTypeEnum._16mL, SourcePowderBottleState = SourceBottleStateEnum.Idl, }); } var powderlist_125 = new ObservableCollection(); for (int i = 0; i < 2; i++) { powderlist_125.Add(new SourcePowderBottleModel() { PosId_InBox = i + 1, HaveBottle = false, RemainWeight = 0, SNCode = string.Empty, PowderBottleType = PowderBottleTypeEnum._125mL, SourcePowderBottleState = SourceBottleStateEnum.Idl, }); } foreach (var sourcePowderBottleBoxModel in sourcePowderBottleBoxModels) { switch (sourcePowderBottleBoxModel.FixtureType) { case BoxTypeEnum._16mL粉末瓶工装: var powderList16mL = File_Operator.DeepCopy(powderlist); // 复制集合 foreach (var bottle in powderList16mL) { bottle.PowderBottleType = PowderBottleTypeEnum._16mL; } var powderBox16mL = new SourcePowderBottleBoxModel { FixtureType = sourcePowderBottleBoxModel.FixtureType, BoxSNCode = sourcePowderBottleBoxModel.BoxSNCode, SourcePowderBottleCollection = powderList16mL, IsDoseFinish = false, IsEmpty = false, IsUseFinsh = false, BoxId_inDoseUpload = sourcePowderBottleBoxModel.BoxId_inDoseUpload, BoxArea = BoxAreaEnum._手套箱传送平台 }; App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourcePowderBottleBoxModel.BoxId_inDoseUpload - 1] = powderBox16mL; }); break; case BoxTypeEnum._125mL粉末瓶工装: var powderList125mL = File_Operator.DeepCopy(powderlist_125); foreach (var bottle in powderList125mL) { bottle.PowderBottleType = PowderBottleTypeEnum._125mL; } var powderBox125mL = new SourcePowderBottleBoxModel_125ml { FixtureType = sourcePowderBottleBoxModel.FixtureType, BoxSNCode = sourcePowderBottleBoxModel.BoxSNCode, SourcePowderBottleCollection = powderList125mL, IsDoseFinish = false, IsEmpty = false, IsUseFinsh = false, BoxId_inDoseUpload = sourcePowderBottleBoxModel.BoxId_inDoseUpload, BoxArea = BoxAreaEnum._手套箱传送平台 }; App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourcePowderBottleBoxModel.BoxId_inDoseUpload - 1] = powderBox125mL; }); break; } } } if (isCloseDoor) await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.CarryOn); await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台下料完成指令,返回-{result.ToJson()}"); //await stationService_Dose.CloseDoor(isCloseDoor, isChangeDeviceState:true); _ = Task.Run(async() => { if (isCloseDoor) { await stationService_Dose.TransferPlateformMoveTo(PlateformPos.TransferIn, new System.Threading.CancellationToken()); } if (isBSRequest) { await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.Idel); } else { await stationService_Dose.TransferPlateformMoveTo(PlateformPos.TransferIn, new System.Threading.CancellationToken()); await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.Finish); } }); } /// /// 验证同步序列数据是否合法 /// /// /// private (bool isSuccess, string msg) ValidateSampleSeqs(SampleSeqRequest sampleSeq) { (bool isSuccess, string msg) result = (true, ""); StringBuilder sb = new StringBuilder(); if(sampleSeq.Config == null || sampleSeq.Config.BoxInfo.Count < 1) { sb.AppendLine($"Config不能为空"); return (false, sb.ToString()); } foreach (var sampleSeqConfig in sampleSeq.Config.BoxInfo) { if (sampleSeqConfig.PosInUpload > 7 || sampleSeqConfig.PosInUpload < 1) sb.AppendLine($"PosInUpload只能在1~7"); if (string.IsNullOrEmpty(sampleSeqConfig.SnCode)) sb.AppendLine($"盒子SN码不能为空"); if (sampleSeqConfig.FixtureType == (int)BoxTypeEnum._300uLTip头工装 || sampleSeqConfig.FixtureType == (int)BoxTypeEnum._50uLTip头工装 || sampleSeqConfig.FixtureType == (int)BoxTypeEnum._1000uLTip头工装) { if (sampleSeqConfig.RemainCount < 0 || sampleSeqConfig.RemainCount > 96) sb.AppendLine($"tip类型的载具RemainCount需要为1~96"); } else { if (sampleSeq.SampleSeqs == null || sampleSeq.SampleSeqs.Count() < 1) { sb.AppendLine("非Tip工装的SampleSeqs不能为空"); return (false, sb.ToString()); } } if (sampleSeqConfig.FixtureType < 1) sb.AppendLine($"请传入治具类型FixtureType字段"); } foreach (var tubeInfo in sampleSeq.SampleSeqs) { var sampleSeqConfig = sampleSeq.Config.BoxInfo.FirstOrDefault(s => s.PosInUpload == int.Parse(tubeInfo.Carrier)); if (sampleSeqConfig == null) { sb.AppendLine($"{tubeInfo.Carrier}在Config中找不到对应的载具!"); continue; } if (sampleSeqConfig.FixtureType == (int)BoxTypeEnum._12mL样品工装 || sampleSeqConfig.FixtureType == (int)BoxTypeEnum._5mL样品工装) { var carridParseOk = int.TryParse(tubeInfo.Carrier, out int CarrierId); var posParseOk = int.TryParse(tubeInfo.Pos, out int PosId); if (!carridParseOk || !posParseOk) { sb.AppendLine($"Carrier或者Pos不是数字!"); continue; } //样品瓶子需要满足样品序列不为空 code作为瓶子信息能为空,area需要是A1,carrier需要1~7,pos需要1~12 if (CarrierId < 1 || CarrierId > 7 || PosId < 1 || PosId > 12) { sb.AppendLine($"对于样品载具Carrier只能是1~7,Pos只能是1~12"); } } else if (sampleSeqConfig.FixtureType == (int)BoxTypeEnum._40mL原液工装 || sampleSeqConfig.FixtureType == (int)BoxTypeEnum._16mL粉末瓶工装 || sampleSeqConfig.FixtureType == (int)BoxTypeEnum._125mL粉末瓶工装) { var carridParseOk = int.TryParse(tubeInfo.Carrier, out int CarrierId); var posParseOk = int.TryParse(tubeInfo.Pos, out int PosId); if (!carridParseOk || !posParseOk) { sb.AppendLine($"Carrier或者Pos不是数字!"); continue; } int maxPosVal = sampleSeqConfig.FixtureType == (int)BoxTypeEnum._40mL原液工装 ? 8 : (sampleSeqConfig.FixtureType == (int)BoxTypeEnum._16mL粉末瓶工装 ? 4 : 2); if (string.IsNullOrEmpty(tubeInfo.Code)) sb.AppendLine($"此工装Code不能为空!"); if (CarrierId < 1 || CarrierId > 7 || PosId < 1 || PosId > maxPosVal) { sb.AppendLine($"对于载具Carrier只能是1~7,Pos只能是1~{maxPosVal}"); } //if (tubeInfo.SampleConfig.RemainWeight <= 0) sb.AppendLine($"RemainWeight字段不能小于等于0!"); } } result.msg = sb.ToString(); result.isSuccess = string.IsNullOrEmpty(result.msg); return result; } private (bool isSuccess, string msg) ValidateSampleSeqsEx(SampleSeqRequestEx sampleSeq) { (bool isSuccess, string msg) result = (true, ""); StringBuilder sb = new StringBuilder(); if (sampleSeq.Config.BoxInfo == null) { sb.AppendLine($"Config不能为空"); return (false, sb.ToString()); } //var sampleSeqConfig = sampleSeq.Config; foreach (var sampleSeqConfig in sampleSeq.Config.BoxInfo) { if (sampleSeqConfig.PosInUpload > 3 || sampleSeqConfig.PosInUpload < 1) sb.AppendLine($"样品载具只能在1~3"); if (string.IsNullOrEmpty(sampleSeqConfig.SnCode)) sb.AppendLine($"盒子SN码不能为空"); if (sampleSeq.SampleSeqs == null || sampleSeq.SampleSeqs.Count() < 1) { sb.AppendLine("SampleSeqs不能为空"); return (false, sb.ToString()); } if (sampleSeqConfig.FixtureType != (int)BoxTypeEnum._12mL样品工装 && sampleSeqConfig.FixtureType != (int)BoxTypeEnum._5mL样品工装) { sb.AppendLine($"样品治具类型FixtureType字段只能位2或3"); return (false, sb.ToString()); } } foreach (var tubeInfo in sampleSeq.SampleSeqs) { var carridParseOk = int.TryParse(tubeInfo.Carrier, out int CarrierId); var posParseOk = int.TryParse(tubeInfo.Pos, out int PosId); if (!carridParseOk || !posParseOk) { sb.AppendLine($"Carrier或者Pos不是数字!"); continue; } //样品瓶子需要满足样品序列不为空 code作为瓶子信息能为空,area需要是A1,carrier需要1~7,pos需要1~12 if (CarrierId < 1 || CarrierId > 7 || PosId < 1 || PosId > 12) { sb.AppendLine($"对于样品载具Carrier只能是1~7,Pos只能是1~12"); } } result.msg = sb.ToString(); result.isSuccess = string.IsNullOrEmpty(result.msg); return result; } private async Task SyncSeqEx(HttpListenerMessage msg) { Response result = new Response() { code = 0, data = true, msg = "" }; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,内容-{str}"); if (string.IsNullOrEmpty(str)) { result.code = 1; result.data = false; result.msg = "序列内容不能为空"; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); return; } try { var sampleSeqRequest = JsonConvert.DeserializeObject(str); var res = ValidateSampleSeqsEx(sampleSeqRequest); if (!res.isSuccess) { result = new Response() { code = 1, data = false, msg = res.msg }; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); return; } List uploadDatas = new List(); foreach (var sampleSeqConfig in sampleSeqRequest.Config.BoxInfo) { UploadBoxModel uploadDataTmp = new UploadBoxModel() { boxId_inDoseUpload = sampleSeqConfig.PosInUpload, boxSNCode = sampleSeqConfig.SnCode, fixtureType = (BoxTypeEnum)sampleSeqConfig.FixtureType, sampleBottles = new List(), sourceLiquidBottles = new List(), sourcePowderBottles = new List(), }; uploadDatas.Add(uploadDataTmp); foreach (var uploadData in uploadDatas) { //var allTubes = sampleSeqRequest.SampleSeqs.Where(s => !string.IsNullOrEmpty(s.Carrier) && s.Carrier.Equals(uploadData.boxId_inDoseUpload.ToString())); var allTubes = sampleSeqRequest.SampleSeqs.Where(s => s.Carrier.Equals(sampleSeqConfig.PosInUpload.ToString())); foreach (var tubeInfo in allTubes) { SampleBottleModel sampleBottleModel = new SampleBottleModel() { SampleSeqId = tubeInfo.SampleSeqId, SampleBottleType = uploadData.fixtureType == BoxTypeEnum._5mL样品工装 ? SampleBottleTypeEnum._5mL : SampleBottleTypeEnum._12mL, BoxSNCode = uploadData.boxSNCode, HaveBottle = true, PosId_InBox = int.Parse(tubeInfo.Pos), SampleContentName = tubeInfo.Code, MaterialDoseFlowList = new ObservableCollection() }; if (tubeInfo.SampleConfig != null && tubeInfo.SampleConfig.MaterialDoseFunctionFlow != null) { foreach (var item in tubeInfo.SampleConfig.MaterialDoseFunctionFlow) { sampleBottleModel.MaterialDoseFlowList.Add( new MaterialDoseFunctionFlow() { FunctionFlowType = (FunctionTypeEnum)item.FunctionFlowType, UseMaterialName = item.UserMaterialName, TargetVolume = item.TargetVolumn } ); } } uploadData.sampleBottles.Add(sampleBottleModel); } var sampleBox = new SampleBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SampleBottleList = new ObservableCollection() }; for (int i = 0; i < 12; i++) { var sampleBottle = uploadData.sampleBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sampleBottle == null) { sampleBottle = new SampleBottleModel(); sampleBottle.HaveBottle = false; sampleBottle.PosId_InBox = i + 1; if (sampleBottle.MaterialDoseFlowList == null) { sampleBottle.MaterialDoseFlowList = new ObservableCollection(); } sampleBox.SampleBottleList.Add(sampleBottle); } else { sampleBottle.SampleBottleType = uploadData.fixtureType == BoxTypeEnum._12mL样品工装 ? SampleBottleTypeEnum._12mL : SampleBottleTypeEnum._5mL; sampleBottle.HaveBottle = true; sampleBottle.BoxSNCode = sampleBox.BoxSNCode; if (sampleBottle.MaterialDoseFlowList == null) { sampleBottle.MaterialDoseFlowList = new ObservableCollection(); } sampleBox.SampleBottleList.Add(sampleBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sampleBox.BoxId_inDoseUpload - 1] = sampleBox; }); } } //var sampleSeqConfig = sampleSeqRequest.Config; await msg.ReplyAsync(JsonConvert.SerializeObject(result)); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); } catch (Exception ex) { result.data = false; result.msg = ex.Message; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); } } /// /// 上料 同步序列 /// /// /// private async Task SyncSeq(HttpListenerMessage msg) { Response result = new Response() { code = 0, data = true, msg = "" }; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,内容-{str}"); if (string.IsNullOrEmpty(str)) { result.code = 1; result.data = false; result.msg = "序列内容不能为空"; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); return; } try { var sampleSeqRequest = JsonConvert.DeserializeObject(str); var res = ValidateSampleSeqs(sampleSeqRequest); if (!res.isSuccess) { result = new Response() { code = 1, data = false, msg = res.msg }; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); return; } List uploadDatas = new List(); foreach (var sampleSeqConfig in sampleSeqRequest.Config.BoxInfo) { UploadBoxModel uploadData = new UploadBoxModel() { boxId_inDoseUpload = sampleSeqConfig.PosInUpload, boxSNCode = sampleSeqConfig.SnCode, fixtureType = (BoxTypeEnum)sampleSeqConfig.FixtureType, RemainCount = sampleSeqConfig.RemainCount, sampleBottles = new List(), sourceLiquidBottles = new List(), sourcePowderBottles = new List(), }; uploadDatas.Add(uploadData); } foreach (var uploadData in uploadDatas) { var allTubes = sampleSeqRequest.SampleSeqs.Where(s => !string.IsNullOrEmpty(s.Carrier) && s.Carrier.Equals(uploadData.boxId_inDoseUpload.ToString())); if (uploadData.fixtureType == BoxTypeEnum._40mL原液工装) { foreach (var tubeInfo in allTubes) { var sourceBottle = new SourceLiquidBottleModel() { BoxSNCode = uploadData.boxSNCode, PosId_InBox = int.Parse(tubeInfo.Pos), SourceLiquidName = tubeInfo.Code, //RemainVolume = tubeInfo.SampleConfig.RemainWeight, //OriginVolume = tubeInfo.SampleConfig.RemainWeight }; uploadData.sourceLiquidBottles.Add(sourceBottle); } } else if (uploadData.fixtureType == BoxTypeEnum._5mL样品工装 || uploadData.fixtureType == BoxTypeEnum._12mL样品工装) { foreach (var tubeInfo in allTubes) { SampleBottleModel sampleBottleModel = new SampleBottleModel() { SampleSeqId = tubeInfo.SampleSeqId, SampleBottleType = uploadData.fixtureType == BoxTypeEnum._5mL样品工装 ? SampleBottleTypeEnum._5mL : SampleBottleTypeEnum._12mL, BoxSNCode = uploadData.boxSNCode, HaveBottle = true, PosId_InBox = int.Parse(tubeInfo.Pos), SampleContentName = tubeInfo.Code, MaterialDoseFlowList = new ObservableCollection() }; if (tubeInfo.SampleConfig != null && tubeInfo.SampleConfig.MaterialDoseFunctionFlow != null) { foreach (var item in tubeInfo.SampleConfig.MaterialDoseFunctionFlow) { sampleBottleModel.MaterialDoseFlowList.Add( new MaterialDoseFunctionFlow() { FunctionFlowType = (FunctionTypeEnum)item.FunctionFlowType, UseMaterialName = item.UserMaterialName, TargetVolume = item.TargetVolumn } ); } } uploadData.sampleBottles.Add(sampleBottleModel); } } else if (uploadData.fixtureType == BoxTypeEnum._16mL粉末瓶工装 || uploadData.fixtureType == BoxTypeEnum._125mL粉末瓶工装) { foreach (var tubeInfo in allTubes) { var sourceBottle = new SourcePowderBottleModel() { BoxSNCode = uploadData.boxSNCode, PosId_InBox = int.Parse(tubeInfo.Pos), SourcePowderName = tubeInfo.Code, //RemainWeight = tubeInfo.SampleConfig.RemainWeight, //OriginWeight = tubeInfo.SampleConfig.RemainWeight, PowderBottleType = uploadData.fixtureType == BoxTypeEnum._16mL粉末瓶工装 ? PowderBottleTypeEnum._16mL : PowderBottleTypeEnum._125mL }; uploadData.sourcePowderBottles.Add(sourceBottle); } } switch (uploadData.fixtureType) { case BoxTypeEnum._40mL原液工装: var sourceBox = new SourceLiquidBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourceLiquidBottleCollection = new ObservableCollection() }; for (int i = 0; i < 8; i++) { var sourceBottle = uploadData.sourceLiquidBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourceBottle == null) { sourceBottle = new SourceLiquidBottleModel(); sourceBottle.HaveBottle = false; sourceBottle.PosId_InBox = i + 1; sourceBox.SourceLiquidBottleCollection.Add(sourceBottle); } else { sourceBottle.HaveBottle = true; sourceBottle.BoxSNCode = sourceBox.BoxSNCode; sourceBox.SourceLiquidBottleCollection.Add(sourceBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourceBox.BoxId_inDoseUpload - 1] = sourceBox; }); break; case BoxTypeEnum._12mL样品工装: case BoxTypeEnum._5mL样品工装: var sampleBox = new SampleBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SampleBottleList = new ObservableCollection() }; for (int i = 0; i < 12; i++) { var sampleBottle = uploadData.sampleBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sampleBottle == null) { sampleBottle = new SampleBottleModel(); sampleBottle.HaveBottle = false; sampleBottle.PosId_InBox = i + 1; if (sampleBottle.MaterialDoseFlowList == null) { sampleBottle.MaterialDoseFlowList = new ObservableCollection(); } sampleBox.SampleBottleList.Add(sampleBottle); } else { sampleBottle.SampleBottleType = uploadData.fixtureType == BoxTypeEnum._12mL样品工装 ? SampleBottleTypeEnum._12mL : SampleBottleTypeEnum._5mL; sampleBottle.HaveBottle = true; sampleBottle.BoxSNCode = sampleBox.BoxSNCode; if (sampleBottle.MaterialDoseFlowList == null) { sampleBottle.MaterialDoseFlowList = new ObservableCollection(); } sampleBox.SampleBottleList.Add(sampleBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sampleBox.BoxId_inDoseUpload - 1] = sampleBox; }); break; case BoxTypeEnum._16mL粉末瓶工装: var sourcePowderBottleBoxModel = new SourcePowderBottleBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourcePowderBottleCollection = new ObservableCollection() }; for (int i = 0; i < 4; i++) { var sourcePowderBottle = uploadData.sourcePowderBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourcePowderBottle == null) { sourcePowderBottle = new SourcePowderBottleModel(); sourcePowderBottle.PosId_InBox = i + 1; sourcePowderBottle.HaveBottle = false; sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._16mL; sourcePowderBottleBoxModel.SourcePowderBottleCollection.Add(sourcePowderBottle); } else { sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._16mL; sourcePowderBottle.HaveBottle = true; sourcePowderBottle.BoxSNCode = sourcePowderBottleBoxModel.BoxSNCode; sourcePowderBottleBoxModel.SourcePowderBottleCollection.Add(sourcePowderBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourcePowderBottleBoxModel.BoxId_inDoseUpload - 1] = sourcePowderBottleBoxModel; }); break; case BoxTypeEnum._125mL粉末瓶工装: var sourcePowderBottleBoxModel_125Ml = new SourcePowderBottleBoxModel_125ml() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, SourcePowderBottleCollection = new ObservableCollection() }; for (int i = 0; i < 2; i++) { var sourcePowderBottle = uploadData.sourcePowderBottles.FirstOrDefault(s => s.PosId_InBox == i + 1); if (sourcePowderBottle == null) { sourcePowderBottle = new SourcePowderBottleModel(); sourcePowderBottle.PosId_InBox = i + 1; sourcePowderBottle.HaveBottle = false; sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._125mL; sourcePowderBottleBoxModel_125Ml.SourcePowderBottleCollection.Add(sourcePowderBottle); } else { sourcePowderBottle.PowderBottleType = PowderBottleTypeEnum._125mL; sourcePowderBottle.HaveBottle = true; sourcePowderBottle.BoxSNCode = sourcePowderBottleBoxModel_125Ml.BoxSNCode; sourcePowderBottleBoxModel_125Ml.SourcePowderBottleCollection.Add(sourcePowderBottle); } } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[sourcePowderBottleBoxModel_125Ml.BoxId_inDoseUpload - 1] = sourcePowderBottleBoxModel_125Ml; }); break; case BoxTypeEnum._50uLTip头工装: case BoxTypeEnum._300uLTip头工装: case BoxTypeEnum._1000uLTip头工装: TipBoxModel tipBoxModel = new TipBoxModel() { BoxId_inDoseUpload = uploadData.boxId_inDoseUpload, FixtureType = uploadData.fixtureType, BoxArea = BoxAreaEnum._手套箱传送平台, BoxSNCode = uploadData.boxSNCode, IsEmpty = false, IsUseFinsh = false, UseIndex = 96 - uploadData.RemainCount + 1, TipItems = new ObservableCollection() }; tipBoxModel.TipType = uploadData.fixtureType == BoxTypeEnum._50uLTip头工装 ? TipTypeEnum._50UL : (uploadData.fixtureType == BoxTypeEnum._300uLTip头工装 ? TipTypeEnum._300UL : TipTypeEnum._1000UL); for (int i = 0; i < tipBoxModel.UseIndex - 1; i++) { tipBoxModel.TipItems.Add(new TipHeadItem() { IsAvailable = false, UseIndex = i + 1 }); } for (int i = tipBoxModel.UseIndex - 1; i < 96; i++) { tipBoxModel.TipItems.Add(new TipHeadItem() { IsAvailable = true, UseIndex = i + 1 }); } App.Current.Dispatcher.Invoke(() => { ProjectPro.TransferArea[tipBoxModel.BoxId_inDoseUpload - 1] = tipBoxModel; }); break; default: break; } } await msg.ReplyAsync(JsonConvert.SerializeObject(result)); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); } catch (Exception ex) { result.data = false; result.msg = ex.Message; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); } } /// /// 上料 同步序列 /// /// /// [Obsolete("弃用,请使用SyncSeq")] private async Task SyncSeq_old(HttpListenerMessage msg) { Response result = new Response() { code = 0, data = true, msg = ""}; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,内容-{str}"); if (string.IsNullOrEmpty(str)) { result.data = false; result.msg = "序列内容不能为空"; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); return; } try { var sampleBottles = JsonConvert.DeserializeObject>(str); if (sampleBottles.Any(s => string.IsNullOrEmpty(s.SampleContentName))) { result.data = false; result.msg = "序列SampleContentName字段不能为空"; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); return; } List allSampleBottles = new List(); var sampleBoxs = ProjectPro.FixtureCacheArea.Where(fx => !fx.IsEmpty && (fx.FixtureType == BoxTypeEnum._12mL样品工装 || fx.FixtureType == BoxTypeEnum._5mL样品工装)); foreach (var sampleBox in sampleBoxs) { var sampleBoxtransfer = sampleBox as SampleBottleBoxModel; allSampleBottles.AddRange(sampleBoxtransfer.SampleBottleList.Where(s => s.HaveBottle)); } if (allSampleBottles.Count < sampleBottles.Count) { result.data = false; result.msg = "工单个数大于可用的空瓶数目"; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); return; } App.Current.Dispatcher.Invoke(() => { for (int i = 0; i < sampleBottles.Count; i++) { allSampleBottles[i].SampleContentName = sampleBottles[i].SampleContentName; allSampleBottles[i].MaterialDoseFlowList = sampleBottles[i].MaterialDoseFlowList; } }); result.msg = $"接口调用成功"; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); } catch (Exception ex) { result.data = false; result.msg = ex.Message; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台同步序列指令,返回-{result.ToJson()}"); } /* //从BS中收到序列,反序列到自己的类 this.UpdateBoxInfo_BS?.Invoke(null, new SampleBottleBoxModel() { BoxId_inDoseUpload = 1, BoxArea = BoxAreaEnum._手套箱传送平台, FixtureType = BoxTypeEnum._12mL样品工装, IsDoseFinish = false, IsUseFinsh = false, BoxSNCode = "BS20240612001", SampleBottleList = new ObservableCollection() { new SampleBottleModel() { HaveBottle=true, SNCode="SAMPLE20240612001", PosId_InBox=1, }, new SampleBottleModel() { HaveBottle=true, SNCode="SAMPLE20240612002", PosId_InBox=2, }, }, }); */ } /// /// 添加序列 /// /// /// private async Task AddSeq(HttpListenerMessage msg) { Response result = new Response() { code = 0, data = true, msg = "" }; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台增加序列指令,内容-{str}"); if (string.IsNullOrEmpty(str)) { result.data = false; result.msg = "序列内容不能为空"; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台增加序列指令,返回-{result.ToJson()}"); return; } try { var sampleBottles = JsonConvert.DeserializeObject>(str); if (sampleBottles.Any(s => string.IsNullOrEmpty(s.SampleContentName))) { result.data = false; result.msg = "序列SampleContentName字段不能为空"; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台增加序列指令,返回-{result.ToJson()}"); return; } var allSampleBottles = ProjectPro.FixtureCacheArea .Where(fx => !fx.IsEmpty && (fx.FixtureType == BoxTypeEnum._12mL样品工装 || fx.FixtureType == BoxTypeEnum._5mL样品工装)) .OfType() .SelectMany(box => box.SampleBottleList) .Where(item => item.HaveBottle && (item.MaterialDoseFlowList == null || item.MaterialDoseFlowList.Count == 0)) .ToList(); if (allSampleBottles.Count < sampleBottles.Count) { result.data = false; result.msg = "工单个数大于可用的空瓶数目"; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台增加序列指令,返回-{result.ToJson()}"); return; } App.Current.Dispatcher.Invoke(() => { for (int i = 0; i < sampleBottles.Count; i++) { allSampleBottles[i].SampleContentName = sampleBottles[i].SampleContentName; allSampleBottles[i].MaterialDoseFlowList = sampleBottles[i].MaterialDoseFlowList; } }); result.msg = $"接口调用成功"; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台增加序列指令,返回-{result.ToJson()}"); } catch (Exception ex) { result.data = false; result.msg = ex.Message; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台增加序列指令,返回-{result.ToJson()}"); } } /// /// 取消序列执行 /// /// /// private async Task DeleteSeq(HttpListenerMessage msg) { Response result = new Response() { code = 0, data = true, msg = "" }; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台删除序列指令,内容-{str}"); if (string.IsNullOrEmpty(str)) { result.data = false; result.msg = "序列内容不能为空"; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台删除序列指令,返回-{result.ToJson()}"); return; } try { var sampleBottles = JsonConvert.DeserializeObject>(str); if (sampleBottles.Any(s => string.IsNullOrEmpty(s.SampleContentName))) { result.data = false; result.msg = "序列SampleContentName字段不能为空"; await msg.ReplyAsync(result.ToJson()); result.code = 1; Logger.LogInformation($"{DateTime.Now}收到机台删除序列指令,返回-{result.ToJson()}"); return; } var allSampleBottles = ProjectPro.FixtureCacheArea .Where(fx => !fx.IsEmpty && (fx.FixtureType == BoxTypeEnum._12mL样品工装 || fx.FixtureType == BoxTypeEnum._5mL样品工装)) .OfType() .SelectMany(box => box.SampleBottleList) .Where(item => item.HaveBottle) .ToList(); App.Current.Dispatcher.Invoke(() => { foreach (var sampleBottle in sampleBottles) { var findBottle = allSampleBottles.FirstOrDefault(x => !string.IsNullOrEmpty(x.SampleContentName) && x.SampleContentName.Equals(sampleBottle.SampleContentName)); if (findBottle != null) { findBottle.SampleContentName = ""; findBottle.MaterialDoseFlowList = new ObservableCollection(); } else { result.data = false; result.msg = $"未找到名称为-{sampleBottle.SampleContentName}的序列\n"; } } }); await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台删除序列指令,返回-{result.ToJson()}"); } catch (Exception ex) { result.data = false; result.msg = ex.Message; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台删除序列指令,返回-{result.ToJson()}"); } } public (bool isSuccess, string msg) ValidateSampleBottle() { (bool isSuccess, string msg) result = (true,""); var allSampleBottles = ProjectPro.FixtureCacheArea .Where(fx => !fx.IsEmpty && (fx.FixtureType == BoxTypeEnum._12mL样品工装 || fx.FixtureType == BoxTypeEnum._5mL样品工装)) .OfType() .SelectMany(box => box.SampleBottleList) .Where(item => item.HaveBottle && item.MaterialDoseFlowList != null && item.MaterialDoseFlowList.Count > 0) .ToList(); if (allSampleBottles == null || allSampleBottles.Count < 1) return (false,"没有需要执行的样品!"); //todo:母液以及粉末都需要有 var allSourceBottles = ProjectPro.FixtureCacheArea .Where(fx => !fx.IsEmpty && (fx.FixtureType == BoxTypeEnum._40mL原液工装)) .OfType() .SelectMany(box => box.SourceLiquidBottleCollection) .Where(item => item.HaveBottle && !string.IsNullOrEmpty(item.SourceLiquidName)) .ToList(); int needTipCount = 0; int allTipCount = 0; foreach (var bottle in allSampleBottles) { foreach (var addMaterial in bottle.MaterialDoseFlowList) { if (addMaterial.FunctionFlowType == FunctionTypeEnum.加液体原料) { if (allSourceBottles.All(b => !b.SourceLiquidName.Equals(addMaterial.UseMaterialName))) { result.isSuccess = false; result.msg += $"{addMaterial.UseMaterialName}在原液区域找不到!"; } needTipCount++; } else { if (ProjectPro.PowderHeaderCacheArea.All(p => !addMaterial.UseMaterialName.Equals(p.SourcePowderName))) { result.isSuccess = false;result.msg += $"{addMaterial.UseMaterialName}在粉末区域找不到!"; } } } } //todo:需要有tip,确保tip足够 for (int i = 0;i<3; i++) { var tipFix = ProjectPro.TipHeadArea[i]; if (!tipFix.HaveBox) continue; allTipCount += tipFix.TipItems.Count(t => t.IsAvailable); } if (needTipCount > allTipCount) { result.isSuccess = false; result.msg += $"tip不够!需要{needTipCount}个现在一共{allTipCount}个!"; } return result; } /// /// 机台控制 /// /// /// private async Task MachineControl(HttpListenerMessage msg) { Response result = new Response() { code = 0, data = true, msg = "" }; string str = msg.GetMessageString(); //string str = await msg.GetRequestBodyStringAsync(); Logger.LogInformation($"{DateTime.Now}收到机台控制指令,内容-{str}"); if (string.IsNullOrEmpty(str)) { result.data = false; result.msg = "未知命令"; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台控制指令,返回-{result.ToJson()}"); return; } try { var controlCmd = JsonConvert.DeserializeObject(str); switch (controlCmd.command) { //start,pause,resume,stop,init, reset, opendoor,load case "init": await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.Runing); await stationService_Dose.WriteCmdToPlc("init"); break; case "reset": await stationService_Dose.WriteCmdToPlc("reset"); break; case "start": //todo需要做数据校验,确保粉末、液体都能找到,且数量是足够的 if (stationService_Dose.StationProp.deviceStatus != Entities.DeviceStatus.Idel) { result.data = false; result.msg = "设备不在就绪状态"; } else { var res = ValidateSampleBottle(); result.data = res.isSuccess; result.msg = res.msg; if (res.isSuccess) { await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.Runing); await stationService_Dose.WriteCmdToPlc("start"); } } break; case "pause": if (stationService_Dose.StationProp.deviceStatus == Entities.DeviceStatus.Runing) { await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.Pause); await stationService_Dose.WriteCmdToPlc("pause"); } else { result.data = false; result.msg = "设备没有运行,不需要暂停"; result.code = 1; } //todo:向PLC发送状态 break; case "resume": if (stationService_Dose.StationProp.deviceStatus == Entities.DeviceStatus.Pause) { await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.Runing); await stationService_Dose.WriteCmdToPlc("start"); } else { result.data = false; result.msg = "设备没有暂停,不需要恢复"; result.code = 1; } //todo:向PLC发送启动 break; case "stop": if (stationService_Dose.StationProp.deviceStatus == Entities.DeviceStatus.Runing || stationService_Dose.StationProp.deviceStatus == Entities.DeviceStatus.Pause) { await stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.Abort); } else { result.data = false; result.msg = "设备没有运行或暂停,不需要取消"; result.code = 1; } break; case "opendoor": await OpenDoor(msg); return; case "load": await this.stationService_Dose.ChangeDeviceStatus(Entities.DeviceStatus.CarryOn); await msg.ReplyAsync(JsonConvert.SerializeObject(result)); Logger.LogInformation($"{DateTime.Now}收到机台开始上料指令,返回-{result.ToJson()}"); _ = Task.Run(async () => { await stationService_Dose.StartLoad(); await stationService_Dose.SendJson((new Guid()).ToString(), "loadsuccess", ""); }); return; default: result.data = false; result.msg = "未知命令";result.code = 1; break; } await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台控制指令,返回-{result.ToJson()}"); } catch (Exception ex) { result.data = false;result.msg = ex.Message; result.code = 1; await msg.ReplyAsync(result.ToJson()); Logger.LogInformation($"{DateTime.Now}收到机台控制指令,返回-{result.ToJson()}"); } } #region 公共转换方法 internal T ConvertApiInputArgs(HttpListenerMessage msg) where T : class { try { string inputJson = msg.GetMessageString(); //string inputJson = msg.GetRequestBodyStringAsync().GetAwaiter().GetResult(); if (!this._appConfigService.BlockKeywords.Contains(msg.Request.Url.Segments[^1])) this.Logger.LogInformation($"API:{msg.Request.Url};Args:{inputJson}"); T request = inputJson.FromJson(); //转换入参数据为实际实体模型对象 return request; } catch (Exception ex) { this.Logger.LogException(ex); } return null; } #endregion } }