C00225155-02/C00225155/MegaRobo.C00225155/MegaRobo.C00225155.AppServer/WorkService.HttpServer.cs

2319 lines
125 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<BaseBottleBox> 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<ApiRouteInfo> _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 = @"
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'/>
<title>设备控制 API - Swagger</title>
<link rel='stylesheet' type='text/css' href='https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui.css' />
<style>html { box-sizing: border-box; overflow: -moz-scrollbars-vertical; overflow-y: scroll; } *, *:before, *:after { box-sizing: inherit; }</style>
</head>
<body>
<div id='swagger-ui'></div>
<script src='https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui-bundle.js'></script>
<script>
window.onload = () => {
SwaggerUIBundle({
url: '/swagger/v1/swagger.json',
dom_id: '#swagger-ui',
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
layout: 'BaseLayout',
deepLinking: true,
showExtensions: false,
showCommonExtensions: false,
});
};
</script>
</body>
</html>";
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<string, object>();
foreach (var api in _registeredApis)
{
var operation = new Dictionary<string, object>
{
["summary"] = api.Summary,
["responses"] = new Dictionary<string, object>
{
["200"] = new Dictionary<string, object>
{
["description"] = "成功"
}
}
};
if (api.HttpMethod == "POST" && api.RequestType != null)
{
var schema = BuildInlineSchema(api.RequestType); // 👈 关键:内联生成 schema
operation["requestBody"] = new Dictionary<string, object>
{
["required"] = true,
["content"] = new Dictionary<string, object>
{
["application/json"] = new Dictionary<string, object>
{
["schema"] = schema
}
}
};
}
paths[api.Path] = new Dictionary<string, object>
{
[api.HttpMethod.ToLower()] = operation
};
}
var openApi = new Dictionary<string, object>
{
["openapi"] = "3.0.3",
["info"] = new Dictionary<string, object>
{
["title"] = "MegaRobo 设备控制 API",
["version"] = "v1"
},
["servers"] = new[]
{
new Dictionary<string, object> { ["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<string, object> { ["type"] = MapDotNetTypeToOpenApi(type) };
}
// 枚举:统一视为 string
if (type.IsEnum)
{
return new Dictionary<string, object> { ["type"] = "string" };
}
// 集合类型List<T>, ObservableCollection<T> 等)
if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type) && type != typeof(string))
{
return new Dictionary<string, object>
{
["type"] = "array",
["items"] = new Dictionary<string, object> { ["type"] = "object" } // 不展开元素类型
};
}
// 对象类型:只取自身 + 基类(直到 ObservableObject 之前)
var properties = new Dictionary<string, object>();
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<T>
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<string, object> { ["type"] = "integer" };
}
// 集合 → array of object
else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(propType) && propType != typeof(string))
{
properties[prop.Name] = new Dictionary<string, object>
{
["type"] = "array",
["items"] = new Dictionary<string, object> { ["type"] = "object" }
};
}
// 简单类型
else if (IsSimpleType(propType))
{
properties[prop.Name] = new Dictionary<string, object>
{
["type"] = MapDotNetTypeToOpenApi(propType)
};
}
// 其他复杂对象 → 统一视为 object不展开
else
{
properties[prop.Name] = new Dictionary<string, object> { ["type"] = "object" };
}
}
current = current.BaseType;
}
return new Dictionary<string, object>
{
["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
/// <summary>
/// 将特定的 HTTP 路径(路由)与对应的处理方法关联
/// HttpListenerService 能够监听这些路径的请求并执行对应的业务逻辑
/// 当传入 deviceKey = "A5" 时,会生成路由:
/// 测试接口:/api/v1/test → 绑定 OnTest 方法,用于测试接口可用性,返回调用成功的 JSON 响应。
/// 设备同步序列接口:/device/A5/sync-seq → 绑定 SyncSeq 方法(目前方法体为空,可后续扩展同步设备序列的逻辑)。
/// </summary>
/// <param name="deviceKey"></param>
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<BaseBottleBox>) });
_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<SampleBottleModel>) });
_registeredApis.Add(new ApiRouteInfo { Path = _add_seq, HttpMethod = "POST", Summary = "添加新序列", RequestType = typeof(List<SampleBottleModel>) });
_registeredApis.Add(new ApiRouteInfo { Path = _delete_seq, HttpMethod = "POST", Summary = "取消序列执行", RequestType = typeof(List<SampleBottleModel>) });
_registeredApis.Add(new ApiRouteInfo { Path = _control, HttpMethod = "POST", Summary = "机台控制指令", RequestType = typeof(ControlCmd) });
}
/// <summary>
/// 测试接口,为了给客户看而使用的接口,后期屏蔽
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
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());
}
/// <summary>
/// 机台信息查询
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
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());
}
/// <summary>
/// 机台信息查询
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
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<int> transferPoss = new List<int>();
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();
});
}
}
/// <summary>
/// 判断上料数据是否合法
/// </summary>
/// <param name="uploadDatas"></param>
/// <returns></returns>
private (bool isSuccess, string msg) ValidateUploadData(List<UploadBoxModel> 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上料数目有限制tipremainCount:1~96、原液瓶(8个)、目标瓶12个、粉末头2/4个不能超过剩余数目
//规则2粉末/tip只能放在67 原液只能放在45 目标瓶只能在123
foreach (var uploadData in uploadDatas)
{
switch (uploadData.fixtureType)
{
case BoxTypeEnum._40mL原液工装:
#region 14581-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 21~3121~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 36-72/41~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 4tip只能放在6-71~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<List<UploadBoxModel>>(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<SourceLiquidBottleModel>()
};
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<SampleBottleModel>()
};
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<MaterialDoseFunctionFlow>();
}
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<MaterialDoseFunctionFlow>();
}
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<SourcePowderBottleModel>()
};
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<SourcePowderBottleModel>()
};
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<TipHeadItem>()
};
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<UploadBoxModel> list = new List<UploadBoxModel>();
UploadBoxModel uploadBoxModel = new UploadBoxModel()
{
boxId_inDoseUpload = 4,
boxSNCode = "1",
fixtureType = BoxTypeEnum._40mL原液工装,
sourceLiquidBottles = new List<SourceLiquidBottleModel>()
{
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<SampleBottleModel>()
{
new SampleBottleModel()
{
PosId_InBox = 1, SNCode = "", SampleContentName = "",
MaterialDoseFlowList = new ObservableCollection<MaterialDoseFunctionFlow>()
{
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<MaterialDoseFunctionFlow>()
{
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<SourcePowderBottleModel>()
{
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());
*/
}
/// <summary>
/// 上耗材
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
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<ConsumableBox>(str);
List<UploadBoxModel> uploadDatas = new List<UploadBoxModel>();
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<SourceLiquidBottleModel>();
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<SourcePowderBottleModel>();
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<SourceLiquidBottleModel>()
};
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<SampleBottleModel>()
};
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<MaterialDoseFunctionFlow>();
}
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<MaterialDoseFunctionFlow>();
}
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<SourcePowderBottleModel>()
};
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<SourcePowderBottleModel>()
};
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<TipHeadItem>()
};
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<SourcePowderBottleBoxModel> sourcePowderBottleBoxModels = null;
if (!string.IsNullOrEmpty(str))
{
try
{
var unLoadData = JsonConvert.DeserializeObject<UnLoadModel>(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<SourcePowderBottleModel>();
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<SourcePowderBottleModel>();
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);
}
});
}
/// <summary>
/// 验证同步序列数据是否合法
/// </summary>
/// <param name="sampleSeqRequests"></param>
/// <returns></returns>
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~7pos需要1~12
if (CarrierId < 1 || CarrierId > 7 || PosId < 1 || PosId > 12)
{
sb.AppendLine($"对于样品载具Carrier只能是1~7Pos只能是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~7Pos只能是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~7pos需要1~12
if (CarrierId < 1 || CarrierId > 7 || PosId < 1 || PosId > 12)
{
sb.AppendLine($"对于样品载具Carrier只能是1~7Pos只能是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<SampleSeqRequestEx>(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<UploadBoxModel> uploadDatas = new List<UploadBoxModel>();
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<SampleBottleModel>(),
sourceLiquidBottles = new List<SourceLiquidBottleModel>(),
sourcePowderBottles = new List<SourcePowderBottleModel>(),
};
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<MaterialDoseFunctionFlow>()
};
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<SampleBottleModel>()
};
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<MaterialDoseFunctionFlow>();
}
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<MaterialDoseFunctionFlow>();
}
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()}");
}
}
/// <summary>
/// 上料 同步序列
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
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<SampleSeqRequest>(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<UploadBoxModel> uploadDatas = new List<UploadBoxModel>();
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<SampleBottleModel>(),
sourceLiquidBottles = new List<SourceLiquidBottleModel>(),
sourcePowderBottles = new List<SourcePowderBottleModel>(),
};
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<MaterialDoseFunctionFlow>()
};
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<SourceLiquidBottleModel>()
};
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<SampleBottleModel>()
};
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<MaterialDoseFunctionFlow>();
}
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<MaterialDoseFunctionFlow>();
}
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<SourcePowderBottleModel>()
};
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<SourcePowderBottleModel>()
};
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<TipHeadItem>()
};
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()}");
}
}
/// <summary>
/// 上料 同步序列
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
[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<List<SampleBottleModel>>(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<SampleBottleModel> allSampleBottles = new List<SampleBottleModel>();
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<SampleBottleModel>()
{
new SampleBottleModel()
{
HaveBottle=true,
SNCode="SAMPLE20240612001",
PosId_InBox=1,
},
new SampleBottleModel()
{
HaveBottle=true,
SNCode="SAMPLE20240612002",
PosId_InBox=2,
},
},
});
*/
}
/// <summary>
/// 添加序列
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
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<List<SampleBottleModel>>(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<SampleBottleBoxModel>()
.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()}");
}
}
/// <summary>
/// 取消序列执行
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
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<List<SampleBottleModel>>(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<SampleBottleBoxModel>()
.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<MaterialDoseFunctionFlow>();
}
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<SampleBottleBoxModel>()
.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<SourceLiquidBottleBoxModel>()
.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;
}
/// <summary>
/// 机台控制
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
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<ControlCmd>(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<T>(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<T>(); //转换入参数据为实际实体模型对象
return request;
}
catch (Exception ex)
{
this.Logger.LogException(ex);
}
return null;
}
#endregion
}
}