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：上料数目有限制，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<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~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<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

    }
}
