kazelee
2025-05-21 a8627a98b82d2364cbe849ca746e72fbab9916e5
重构代码修复事务问题,测试完善后台盘点功能
25 文件已重命名
13个文件已添加
19个文件已修改
29个文件已删除
4879 ■■■■ 已修改文件
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/05336dc4-4629-4a97-bb9a-4516a380cd0d.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/1a441e71-f454-4033-af8e-db39c2339a05.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/bd85daa8-32a5-4c87-9f8f-b1ed513fa1f8.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/c94de693-d780-402e-840f-826433af2f96.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
AppStart/Config.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
AppStart/Settings.cs 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
App_Start/Startup.cs 补丁 | 查看 | 原始文档 | blame | 历史
App_Start/SwaggerConfig.cs 补丁 | 查看 | 原始文档 | blame | 历史
App_Start/SwaggerControllerDescProvider.cs 补丁 | 查看 | 原始文档 | blame | 历史
Consts/AgvStateCode.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/AgvStateName.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/AreaCode.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/LockStateCode.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/LockStateName.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Consts/TaskName.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/ApiModel.cs 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/DebugController.cs 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controllers/MoboxController.cs 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/GZRobot.cs 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/HanAo.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/NDC.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/NDCApi.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/NDCHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Request/AgvRequest.cs 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Request/DebugRequest.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Request/ErpRequest.cs 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Request/MoboxRequest.cs 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Response/AgvResponse.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Response/DebugResponse.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Response/ErpResponse.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Dtos/Response/MoboxResponse.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3.AnGang.csproj 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/AgvHelper.cs 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Helpers/DbHelper.cs 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/BaseModel.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/DebugModel.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_CAR_IN.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_CG_Detail.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Container.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Inbound_Order.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Loc_Container.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Location.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Outbound_Order.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Task.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Task_Action.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_WorkOrder.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Program.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServiceCore/Monitor.cs 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServiceCore/WCSCore.cs 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/DebugService.cs 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/ErpService.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Services/MoboxService.cs 363 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/AgvController.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ApiHelper.cs 612 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ApiModel.cs 481 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/DebugController.cs 320 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ErpController.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/MoboxController.cs 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/WmsController.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/config.json 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
core/Monitor.cs 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
core/WCSCore.cs 160 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
core/WMSCore.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/ModbusHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/OpcUaHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/PlcHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/S7Helper.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/SnapDevice.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/SnapManager.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/TcpClient.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/TcpServer.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/TN_Count_CG_Detail.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/TN_Count_Diff.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/TN_Count_Order.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/TN_Count_Plan.cs 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
process/DeviceProcess.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
process/TaskProcess.cs 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/HttpHelper.cs 补丁 | 查看 | 原始文档 | blame | 历史
util/LogHelper.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/Settings.cs 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/SqlHelper.cs 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wms/ContainerHelper.cs 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wms/LocationHelper.cs 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wms/SYSHelper.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wms/WCSHelper.cs 70 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wms/WMSHelper.cs 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/05336dc4-4629-4a97-bb9a-4516a380cd0d.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/1a441e71-f454-4033-af8e-db39c2339a05.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/bd85daa8-32a5-4c87-9f8f-b1ed513fa1f8.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/c94de693-d780-402e-840f-826433af2f96.vsidx
Binary files differ
AppStart/Config.cs
File was deleted
AppStart/Settings.cs
File was deleted
App_Start/Startup.cs
App_Start/SwaggerConfig.cs
App_Start/SwaggerControllerDescProvider.cs
Consts/AgvStateCode.cs
File was deleted
Consts/AgvStateName.cs
File was deleted
Consts/AreaCode.cs
File was deleted
Consts/LockStateCode.cs
File was deleted
Consts/LockStateName.cs
File was deleted
Consts/TaskName.cs
File was deleted
Controllers/ApiModel.cs
File was deleted
Controllers/DebugController.cs
File was deleted
Controllers/MoboxController.cs
File was deleted
Dispatch/GZRobot.cs
@@ -2,26 +2,19 @@
using System.Collections.Generic;
using System.IdentityModel.Protocols.WSTrust;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using HH.WCS.Mobox3.AnGang.Helpers;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.Services;
using HH.WCS.Mobox3.AnGang.core;
using HH.WCS.Mobox3.AnGang.models;
using Newtonsoft.Json;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.AgvRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.AgvResponse;
namespace HH.WCS.Mobox3.AnGang.Dispatch {
namespace HH.WCS.Mobox3.AnGang.dispatch {
    /// <summary>
    /// 国自调度辅助类
    /// </summary>
    public class GZRobot {
        private static readonly HttpHelper apiHelper = new HttpHelper();
        private static readonly string baseUrl = AppStart.Settings.Config.RCSApiUrl;//配置文件获取国自调度地址
        private static readonly string baseUrl = Settings.RCSApiUrl;//配置文件获取国自调度地址
        //private static readonly string logName = "guozi";
        public static List<IOState> GetIO() {
            var result = apiHelper.Get(baseUrl + "api/engine/view/iostates/");
@@ -33,7 +26,6 @@
            var result = apiHelper.Post(baseUrl + "api/engine/tasks/iostates/", JsonConvert.SerializeObject(data));
            var dataResult = JsonConvert.DeserializeObject<gzResult<IOStatesInfoResult>>(result);
        }
        public static int CreateOrder(string taskNo, int priority, string param, string ts = "churuku", string created_user = "hanhe") {
            LogHelper.Info($"CreateOrder参数信息:taskNo:{taskNo},priority:{priority},param:{param},ts:{ts},created_user:{created_user}", "API");
@@ -157,7 +149,14 @@
            if (agv.state != 0) {
                agv.task_no = model.orderName;
                agv.forklift_no = model.agvIDList;
                AgvService.OperateAgvTaskStatus(agv);
                WCSCore.OperateAgvTaskStatus(agv);
            }
            else {
                result.resultCode = 2;
                result.orderID = model.orderID;
                result.msg = "反馈订单状态失败,orderStatus参数不正确";
                LogHelper.Info(result.msg, "API");
                return result;
            }
            result.resultCode = 0;
Dispatch/HanAo.cs
@@ -4,7 +4,7 @@
using System.Collections.Generic;
using System.Web.Services.Description;
namespace HH.WCS.Mobox3.AnGang.Dispatch {
namespace HH.WCS.Mobox3.AnGang.dispatch {
    /// <summary>
    /// 国自调度辅助类
    /// </summary>
Dispatch/NDC.cs
@@ -5,7 +5,7 @@
using Newtonsoft.Json;
namespace HH.WCS.Mobox3.AnGang.Dispatch {
namespace HH.WCS.Mobox3.AnGang.dispatch {
    public class NDC
    {
        private static HostToAGV callClient = null;
Dispatch/NDCApi.cs
@@ -1,19 +1,18 @@
using System;
using System.Collections.Generic;
using HH.WCS.Mobox3.AnGang.AppStart;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
namespace HH.WCS.Mobox3.AnGang.Dispatch {
namespace HH.WCS.Mobox3.AnGang.dispatch {
    public class NDCApi
    {
        public static string NDCApiUrl { set; get; }
        static NDCApi()
        {
            NDCApiUrl = Settings.Config.NDCApiUrl;
            NDCApiUrl = Settings.NDCApiUrl;
        }
Dispatch/NDCHelper.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
namespace HH.WCS.Mobox3.AnGang.Dispatch
namespace HH.WCS.Mobox3.AnGang.dispatch
{
    public class NDCHelper
    {
Dtos/Request/AgvRequest.cs
File was deleted
Dtos/Request/DebugRequest.cs
File was deleted
Dtos/Request/ErpRequest.cs
File was deleted
Dtos/Request/MoboxRequest.cs
File was deleted
Dtos/Response/AgvResponse.cs
File was deleted
Dtos/Response/DebugResponse.cs
File was deleted
Dtos/Response/ErpResponse.cs
File was deleted
Dtos/Response/MoboxResponse.cs
File was deleted
HH.WCS.Mobox3.AnGang.csproj
@@ -257,76 +257,60 @@
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="AppStart\Config.cs" />
    <Compile Include="Consts\AgvStateCode.cs" />
    <Compile Include="Consts\AgvStateName.cs" />
    <Compile Include="Consts\AreaCode.cs" />
    <Compile Include="Consts\LockStateCode.cs" />
    <Compile Include="Consts\LockStateName.cs" />
    <Compile Include="Consts\TaskName.cs" />
    <Compile Include="Controllers\DebugController.cs" />
    <Compile Include="Controllers\ErpController.cs" />
    <Compile Include="Controllers\MoboxController.cs" />
    <Compile Include="Controllers\AgvController.cs" />
    <Compile Include="Controllers\ApiModel.cs" />
    <Compile Include="AppStart\SwaggerControllerDescProvider.cs" />
    <Compile Include="Devices\SnapDevice.cs" />
    <Compile Include="Devices\SnapManager.cs" />
    <Compile Include="Dtos\Request\DebugRequest.cs" />
    <Compile Include="Dtos\Request\ErpRequest.cs" />
    <Compile Include="Dtos\Response\DebugResponse.cs" />
    <Compile Include="Dtos\Response\ErpResponse.cs" />
    <Compile Include="Helpers\AgvHelper.cs" />
    <Compile Include="Helpers\DbHelper.cs" />
    <Compile Include="Models\DebugModel.cs" />
    <Compile Include="Models\TN_Inbound_Order.cs" />
    <Compile Include="Models\TN_Outbound_Order.cs" />
    <Compile Include="ServiceCore\WMSCore.cs" />
    <Compile Include="Models\BaseModel.cs" />
    <Compile Include="Services\DebugService.cs" />
    <Compile Include="Devices\ModbusHelper.cs" />
    <Compile Include="Devices\OpcUaHelper.cs" />
    <Compile Include="Devices\PlcHelper.cs" />
    <Compile Include="Devices\S7Helper.cs" />
    <Compile Include="Devices\TcpClient.cs" />
    <Compile Include="Devices\TcpServer.cs" />
    <Compile Include="Dispatch\GZRobot.cs" />
    <Compile Include="Dispatch\HanAo.cs" />
    <Compile Include="Dispatch\NDC.cs" />
    <Compile Include="ServiceCore\Monitor.cs" />
    <Compile Include="Dispatch\NDCApi.cs" />
    <Compile Include="Dtos\Request\AgvRequest.cs" />
    <Compile Include="Dtos\Request\MoboxRequest.cs" />
    <Compile Include="Dtos\Response\AgvResponse.cs" />
    <Compile Include="Dtos\Response\MoboxResponse.cs" />
    <Compile Include="Models\TN_CG_Detail.cs" />
    <Compile Include="Models\TN_CAR_IN.cs" />
    <Compile Include="Models\TN_Container.cs" />
    <Compile Include="Models\TN_Location.cs" />
    <Compile Include="Models\TN_Loc_Container.cs" />
    <Compile Include="Models\TN_WorkOrder.cs" />
    <Compile Include="Models\TN_Task.cs" />
    <Compile Include="Models\TN_Task_Action.cs" />
    <Compile Include="Helpers\DeviceProcess.cs" />
    <Compile Include="ServiceCore\WCSCore.cs" />
    <Compile Include="Controllers\WmsController.cs" />
    <Compile Include="Dispatch\HostToAGV.cs" />
    <Compile Include="Helpers\TaskHelper.cs" />
    <Compile Include="Services\AgvService.cs" />
    <Compile Include="Services\ErpService.cs" />
    <Compile Include="Services\MoboxService.cs" />
    <Compile Include="Helpers\LogHelper.cs" />
    <Compile Include="Helpers\ContainerHelper.cs" />
    <Compile Include="Helpers\LocationHelper.cs" />
    <Compile Include="Helpers\WMSHelper.cs" />
    <Compile Include="Helpers\SysHelper.cs" />
    <Compile Include="api\ApiHelper.cs" />
    <Compile Include="api\DebugController.cs" />
    <Compile Include="api\ErpController.cs" />
    <Compile Include="api\MoboxController.cs" />
    <Compile Include="api\AgvController.cs" />
    <Compile Include="api\ApiModel.cs" />
    <Compile Include="App_Start\SwaggerControllerDescProvider.cs" />
    <Compile Include="device\SnapDevice.cs" />
    <Compile Include="device\SnapManager.cs" />
    <Compile Include="models\TN_Count_CG_Detail.cs" />
    <Compile Include="models\TN_Count_Diff.cs" />
    <Compile Include="models\TN_Count_Order.cs" />
    <Compile Include="models\TN_Count_Plan.cs" />
    <Compile Include="models\TN_Inbound_Order.cs" />
    <Compile Include="models\TN_Outbound_Order.cs" />
    <Compile Include="core\WMSCore.cs" />
    <Compile Include="models\BaseModel.cs" />
    <Compile Include="device\ModbusHelper.cs" />
    <Compile Include="device\OpcUaHelper.cs" />
    <Compile Include="device\PlcHelper.cs" />
    <Compile Include="device\S7Helper.cs" />
    <Compile Include="device\TcpClient.cs" />
    <Compile Include="device\TcpServer.cs" />
    <Compile Include="dispatch\GZRobot.cs" />
    <Compile Include="dispatch\HanAo.cs" />
    <Compile Include="dispatch\NDC.cs" />
    <Compile Include="core\Monitor.cs" />
    <Compile Include="dispatch\NDCApi.cs" />
    <Compile Include="models\TN_CG_Detail.cs" />
    <Compile Include="models\TN_CAR_IN.cs" />
    <Compile Include="models\TN_Container.cs" />
    <Compile Include="models\TN_Location.cs" />
    <Compile Include="models\TN_Loc_Container.cs" />
    <Compile Include="models\TN_WorkOrder.cs" />
    <Compile Include="models\TN_Task.cs" />
    <Compile Include="models\TN_Task_Action.cs" />
    <Compile Include="process\DeviceProcess.cs" />
    <Compile Include="core\WCSCore.cs" />
    <Compile Include="api\WmsController.cs" />
    <Compile Include="dispatch\HostToAGV.cs" />
    <Compile Include="util\LogHelper.cs" />
    <Compile Include="wms\ContainerHelper.cs" />
    <Compile Include="wms\LocationHelper.cs" />
    <Compile Include="wms\WMSHelper.cs" />
    <Compile Include="wms\SYSHelper.cs" />
    <Compile Include="process\TaskProcess.cs" />
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="AppStart\Settings.cs" />
    <Compile Include="AppStart\Startup.cs" />
    <Compile Include="Dispatch\NDCHelper.cs" />
    <Compile Include="Helpers\HttpHelper.cs" />
    <Compile Include="Helpers\WCSHelper.cs" />
    <Compile Include="util\Settings.cs" />
    <Compile Include="App_Start\Startup.cs" />
    <Compile Include="dispatch\NDCHelper.cs" />
    <Compile Include="util\HttpHelper.cs" />
    <Compile Include="wms\WCSHelper.cs" />
    <Compile Include="util\SqlHelper.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include=".editorconfig" />
Helpers/AgvHelper.cs
File was deleted
Helpers/DbHelper.cs
File was deleted
Models/BaseModel.cs
@@ -2,7 +2,7 @@
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    /// <summary>
    /// 【框架】模板抽象类:基本表数据模型
    /// </summary>
Models/DebugModel.cs
File was deleted
Models/TN_CAR_IN.cs
@@ -5,7 +5,7 @@
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Models
namespace HH.WCS.Mobox3.AnGang.models
{
    /// <summary>
    /// 容器生产车数关联子表
Models/TN_CG_Detail.cs
@@ -1,6 +1,6 @@
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    /// <summary>
    /// 物料-容器 关系表
    /// </summary>
@@ -37,7 +37,6 @@
        /// 数量:这里当做重量
        /// </summary>
        public float F_QTY { get; set; } = 0f;
        /// <summary>
        /// 图片链接
Models/TN_Container.cs
@@ -1,7 +1,7 @@
using SqlSugar;
using System.Collections.Generic;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    [SugarTable("TN_Container")]
    public class TN_Container : BaseModel {
        public string S_CODE { get; set; }
Models/TN_Inbound_Order.cs
@@ -4,7 +4,7 @@
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    public class TN_Inbound_Order : BaseModel {
        /// <summary>
        /// 储位码
Models/TN_Loc_Container.cs
@@ -1,7 +1,7 @@
using SqlSugar;
using System.Collections.Generic;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    //TN_Loc_Container
    //LocCntrRel
    [SugarTable("TN_Loc_Container")]
Models/TN_Location.cs
@@ -1,7 +1,7 @@
using SqlSugar;
using System.Collections.Generic;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    [SugarTable("TN_Location")]
    public class TN_Location : BaseModel {
Models/TN_Outbound_Order.cs
@@ -4,7 +4,7 @@
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    public class TN_Outbound_Order : BaseModel {
        /// <summary>
        /// 储位码
Models/TN_Task.cs
@@ -1,7 +1,7 @@
using SqlSugar;
using System;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    [SugarTable("TN_Task")]
    public class TN_Task : BaseModel {
Models/TN_Task_Action.cs
@@ -1,6 +1,6 @@
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    [SugarTable("TN_Task_Action")]
    public  class TN_Task_Action : BaseModel
    {
Models/TN_WorkOrder.cs
@@ -1,6 +1,6 @@
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.Models {
namespace HH.WCS.Mobox3.AnGang.models {
    /// <summary>
    /// 生产工单
    /// </summary>
Program.cs
@@ -3,8 +3,7 @@
using System.Threading;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.AppStart;
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.device;
using Microsoft.Owin.Hosting;
@@ -59,7 +58,7 @@
            Console.WriteLine("Startup ApiController");
            Task.Run(() =>
            {
                var url = Settings.Config.WebApiUrl;
                var url = Settings.WebApiUrl;
                Console.WriteLine(url);
                using (WebApp.Start<Startup>(url))
                {
@@ -74,8 +73,8 @@
        /// </summary>
        private static void StartTcp()
        {
            var tcpServerIP = Settings.Config.TCPServerIP;
            var tcpServerPort = Settings.Config.TCPServerPort;
            var tcpServerIP = Settings.TCPServerIP;
            var tcpServerPort = Settings.TCPServerPort;
            new TcpServer(tcpServerIP, tcpServerPort);
        }
@@ -115,8 +114,7 @@
        }
        private static void StartSnap() {
            //new SnapManager(Settings.Snap);
            new SnapManager(Settings.Config.Snap[0]);
            new SnapManager(Settings.Snaps[0]);
        }
        public class WorkThread
@@ -127,11 +125,7 @@
                // 添加任务推送线程
                //tasks.Add(GetTask(WCSCore.Dispatch));
                ////添加自定义线程
                //tasks.Add(GetTask(Monitor.CheckEmptyCnt));//检测空托盘
                ////根据S7/Modbus协议判断输送线的信号  原材料产线库区=>满托缓存库区,空托缓存库区=>原材料产线库区
                //tasks.Add(GetTask(Monitor.CheckS7Devices));
                Task.WaitAll(tasks.ToArray());
            }
ServiceCore/Monitor.cs
File was deleted
ServiceCore/WCSCore.cs
File was deleted
Services/DebugService.cs
File was deleted
Services/ErpService.cs
File was deleted
Services/MoboxService.cs
File was deleted
api/AgvController.cs
File was renamed from Controllers/AgvController.cs
@@ -1,21 +1,19 @@
using HH.WCS.Mobox3.AnGang.ServiceCore;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.core;
using HH.WCS.Mobox3.AnGang.dispatch;
using HH.WCS.Mobox3.AnGang.process;
using HH.WCS.Mobox3.AnGang.Helper;
using HH.WCS.Mobox3.AnGang.wms;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Http;
using static HH.WCS.Mobox3.AnGang.Dispatch.NDC;
using static HH.WCS.Mobox3.AnGang.dispatch.NDC;
using System.Linq;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Services;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.AgvRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.AgvResponse;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
namespace HH.WCS.Mobox3.AnGang.Controllers
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
namespace HH.WCS.Mobox3.AnGang.api
{
    /// <summary>
    /// 设备信息上报(hosttoagv上报、杭奥堆垛机、国自agv)
@@ -55,7 +53,7 @@
        [HttpPost]
        [Route("safetyInteraction")]
        public ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
            return AgvService.SafetyInteraction(model);
            return WCSCore.SafetyInteraction(model);
        }
    }
}
api/ApiHelper.cs
New file
@@ -0,0 +1,612 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.models;
using HH.WCS.Mobox3.AnGang.util;
using HH.WCS.Mobox3.AnGang.wms;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
using static HH.WCS.Mobox3.AnGang.api.OtherModel;
namespace HH.WCS.Mobox3.AnGang.api {
    public class ApiHelper {
        /// <summary>
        /// 产品入库(PDA)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult Inbound(InboundInfo model) {
            var taskName = TaskName.产品入库;
            var db = new SqlHelper<object>().GetInstance();
            try {
                // 起点位置必须:为空、无锁、启用、属于收发区域
                var startLoc = db.Queryable<TN_Location>()
                    .Where(a => a.S_CODE == model.StartLoc)
                    .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y")
                    .Where(a => a.N_CURRENT_NUM == 0)
                    .Where(a => a.S_AREA_CODE == "SFQ")
                    .First();
                if (startLoc == null) {
                    return NewSimpleResult(1, $"起点位置{model.StartLoc}不存在!");
                }
                // 容器 ID 和 物料 ID 未指定,由系统直接生成
                var cntId = Guid.NewGuid().ToString("D");
                var CgId = Guid.NewGuid().ToString("D");
                // 初始是没有绑定信息的,先将起点位置与容器绑定,容器与物料绑定
                var locCntrRel = new TN_Loc_Container() {
                    S_LOC_CODE = startLoc.S_CODE,
                    S_CNTR_CODE = cntId,
                };
                var cgDetail = new TN_CG_Detail() {
                    S_ITEM_CODE = CgId,
                    S_CNTR_CODE = cntId,
                };
                var endLocCode = "0"; // 假的默认终点地址
                // 指定货位排号(不能为空、空字符串或空格)
                if (model.Row != null && model.Row.Trim() != "") {
                    endLocCode = model.Row; // 用排号字符串当做假地址
                    if (!int.TryParse(model.Row.Trim(), out int row)) {
                        return NewSimpleResult(2, $"{model.Row} 不合法:无法转成整数类型");
                    }
                    // 货架排号只能是 0 - 8
                    if (row <= 0 || row > 8) {
                        return NewSimpleResult(2, $"货架号 {model.Row} 必须是1-8之间的整数");
                    }
                }
                var task = WCSHelper.BuildInboundTask(startLoc, endLocCode, cntId);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                // 无论是否选择终点货架,都等到称重之后再计算终点货位
                using (var tran = db.Ado.UseTran()) {
                    if (db.Insertable<TN_Loc_Container>(locCntrRel).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"插入货位容器关系表失败:货位{locCntrRel.S_LOC_CODE},容器{locCntrRel.S_CNTR_CODE}");
                    }
                    if (db.Insertable<TN_CG_Detail>(cgDetail).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"插入容器货品明细表失败:容器{cgDetail.S_CNTR_CODE},物料{cgDetail.S_ITEM_CODE}");
                    }
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"更新起点货位锁状态失败:起点货位{startLoc.S_CODE}");
                    }
                    if (db.Insertable<TN_Task>(task).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成任务 {taskName} 失败:容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLocCode} ,终点货位未指定");
                    }
                    tran.CommitTran();
                    return NewSimpleResult(0,
                        $"生成任务 {taskName} 成功:容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLocCode} ,终点货位未指定");
                }
            }
            catch (Exception ex) {
                return NewSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// PDA选择终点货位
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult SelectLocation(SelectLocationInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            try {
                // 任务号存在:终点货架和终点位置为空,且任务为产品入库(PDA)
                var task = db.Queryable<TN_Task>()
                    .Where(a => a.S_B_STATE == "取货完成" && a.S_TYPE == TaskName.产品入库)
                    .OrderBy(a => a.T_CREATE, SqlSugar.OrderByType.Desc).First();
                if (task == null) {
                    return NewSimpleResult(2, $"当前不存在状态为 取货完成 的 产品入库 任务");
                }
                if (task.S_END_LOC != null && task.S_END_LOC != "0") {
                    return NewSimpleResult(3, $"该任务已有终点");
                }
                var cgDetail = db.Queryable<TN_CG_Detail>()
                    .Where(a => a.S_CNTR_CODE == task.S_CNTR_CODE).First();
                if (cgDetail == null) {
                    return NewSimpleResult(4, $"托盘物料不存在");
                }
                var endLoc = new TN_Location();
                if (cgDetail.F_QTY > 1500) {
                    // 重量超过1.5t,需要选择1-3层货架
                    endLoc = db.Queryable<TN_Location>()
                        .Where(a => a.S_CODE == model.endLoc)
                        .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y")
                        .Where(a => a.N_CURRENT_NUM == 0)
                        .Where(a => a.S_AREA_CODE == "HJQ")
                        .Where(a => a.N_LAYER <= 3)
                        .First();
                }
                else if (cgDetail.F_QTY > 0) {
                    endLoc = db.Queryable<TN_Location>()
                        .Where(a => a.S_CODE == model.endLoc)
                        .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y")
                        .Where(a => a.N_CURRENT_NUM == 0)
                        .Where(a => a.S_AREA_CODE == "HJQ")
                        //.Where(a => a.N_LAYER <= 3)
                        .First();
                }
                else {
                    return NewSimpleResult(5, $"物料重量信息不合法:{cgDetail.F_QTY}");
                }
                // 没有符合条件的货位
                if (endLoc == null) {
                    return NewSimpleResult(6, $"货位{model.endLoc}不存在,或不满足称重放置要求");
                }
                // 修改任务终点为PDA指定终点
                task.S_END_LOC = endLoc.S_CODE;
                LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(task).UpdateColumns(a => a.S_END_LOC).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(7, $"任务{task.S_CODE}修改失败,修改终点位置为{endLoc.S_CODE}");
                    }
                    if (db.Updateable<TN_Location>(endLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(7, $"任务{task.S_CODE}修改失败,修改终点位置为{endLoc.S_CODE}");
                    }
                    tran.CommitTran();
                    return NewSimpleResult(0, $"任务{task.S_CODE}修改成功,修改终点位置为{endLoc.S_CODE}");
                }
            }
            catch (Exception ex) {
                return NewSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 产品部分出库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult PartOutbound(PartOutboundInfo model) {
            var taskName = TaskName.产品部分出库;
            var db = new SqlHelper<object>().GetInstance();
            try {
                // 起点位置:货架(有货、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>()
                    .Where(a => a.S_CODE == model.startLoc)
                    .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y")
                    .Where(a => a.N_CURRENT_NUM == 1)
                    .First();
                if (startLoc == null) {
                    return NewSimpleResult(2, $"起点位置 {model.startLoc} 不存在或不具备取货要求");
                }
                var locCntrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.startLoc);
                if (locCntrRel == null) {
                    return NewSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可出库的物料");
                }
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == "SFQ");
                if (endLoc == null) {
                    return NewSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
                }
                var cntId = locCntrRel.S_CNTR_CODE;
                var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货位 {endLoc.S_CODE}");
                    }
                    if (db.Updateable<TN_Location>(endLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                    }
                    if (db.Insertable<TN_Task>(task).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                    }
                    tran.CommitTran();
                    return NewSimpleResult(0,
                        $"生成 {taskName} 成功,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                }
            }
            catch (Exception ex) {
                return NewSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 产品部分回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult PartInbound(PartInboundInfo model) {
            var taskName = TaskName.产品部分回库;
            var db = new SqlHelper<object>().GetInstance();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == "SFQ");
                if (startLoc == null) {
                    return NewSimpleResult(2, $"起点位置 {model.startLoc} 不符合回库条件");
                }
                var locCntrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.startLoc);
                if (locCntrRel == null) {
                    return NewSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可回库的物料");
                }
                // 终点位置:货架(没有货物,没有锁)
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                if (endLoc == null) {
                    return NewSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
                }
                var cntId = locCntrRel.S_CNTR_CODE;
                var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货位 {endLoc.S_CODE}");
                    }
                    if (db.Updateable<TN_Location>(endLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                    }
                    if (db.Insertable<TN_Task>(task).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                    }
                    tran.CommitTran();
                    return NewSimpleResult(0,
                        $"生成 {taskName} 成功,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                }
            }
            catch (Exception ex) {
                return NewSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        public static SimpleResult CreateCountPlan(CreateCountPlanInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            try {
                var countPlan = new TN_Count_Plan() {
                    S_CP_NO = GenerateNo("盘点计划", "CP"),
                    S_TYPE = model.countType,
                };
                if (model.countType == "货位") {
                    countPlan.S_LOC_CODE = model.targetId;
                }
                else if (model.countType == "物料") {
                    countPlan.S_ITEM_CODE = model.targetId;
                }
                else {
                    return NewSimpleResult(2, $"创建盘点计划失败:不合法的盘点类型 '{model.countType}'");
                }
                if (db.Insertable<TN_Count_Plan>(countPlan).ExecuteCommand() <= 0) {
                    return NewSimpleResult(2, "创建盘点计划失败");
                }
                return NewSimpleResult(0, "创建盘点计划成功");
            }
            catch (Exception ex) {
                return NewSimpleResult(1, ex.Message);
            }
        }
        public static SimpleResult CreateCountOrder(CreateCountOrderInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            var info = "";
            try {
                var countPlan = db.Queryable<TN_Count_Plan>()
                    .Where(a => a.S_CP_NO == model.planId).First();
                if (countPlan == null) {
                    return NewSimpleResult(2, $"盘点计划单号 '{model.planId}' 不存在");
                }
                var countOrder = new TN_Count_Order() {
                    S_CP_NO = model.planId,
                    S_COUNT_NO = GenerateNo("盘点单", "CN"),
                };
                var countDetailList = new List<TN_Count_CG_Detail>();
                if (countPlan.S_TYPE == "货位") {
                    var cgDetail = db.Queryable<TN_Location, TN_Loc_Container, TN_CG_Detail>
                        ((l, c, d) => l.S_CODE == c.S_LOC_CODE && c.S_CNTR_CODE == d.S_CNTR_CODE)
                        .Where(l => l.S_CODE == countPlan.S_LOC_CODE)
                        .Select((l, c, d) => d).First();
                    var countDetail = new TN_Count_CG_Detail {
                        S_COUNT_NO = countOrder.S_COUNT_NO,
                        S_CNTR_CODE = cgDetail.S_CNTR_CODE,
                        S_ITEM_CODE = cgDetail.S_ITEM_CODE,
                    };
                    countDetailList.Add(countDetail);
                }
                else if (countPlan.S_TYPE == "物料") {
                    var cgDetailList = db.Queryable<TN_CG_Detail>()
                        .Where(d => d.S_ITEM_CODE == countPlan.S_ITEM_CODE).ToList();
                    foreach (var cgDetail in cgDetailList) {
                        var countDetail = new TN_Count_CG_Detail {
                            S_COUNT_NO = countOrder.S_COUNT_NO,
                            S_CNTR_CODE = cgDetail.S_CNTR_CODE,
                            S_ITEM_CODE = cgDetail.S_ITEM_CODE,
                        };
                        countDetailList.Add(countDetail);
                    }
                }
                else {
                    return NewSimpleResult(3, $"计划单'{model.planId}'的类型{countPlan.S_TYPE}不合法");
                }
                using (var tran = db.Ado.UseTran()) {
                    if (db.Insertable<TN_Count_Order>(countOrder).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        info = "创建盘点单失败";
                        return NewSimpleResult(2, info);
                    }
                    if (db.Insertable<TN_Count_CG_Detail>(countDetailList).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        info = "创建盘点单明细失败";
                        return NewSimpleResult(3, info);
                    }
                    tran.CommitTran();
                }
                return NewSimpleResult(0, "创建盘点单成功");
            }
            catch (Exception ex) {
                return NewSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        public static SimpleResult CountProduct(CountProductInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            try {
                var cgDetail = db.Queryable<TN_CG_Detail>()
                    .Where(d => d.S_CNTR_CODE == model.cntrCode).First();
                if (cgDetail == null) {
                    return NewSimpleResult(2, $"找不到容器号'{model.cntrCode}'对应的物料");
                }
                var countDiff = new TN_Count_Diff {
                    S_CNTR_CODE = cgDetail.S_CNTR_CODE,
                    F_ACTUAL_QTY = model.qty
                };
                if (db.Insertable<TN_Count_Diff>(countDiff).ExecuteCommand() <= 0) {
                    return NewSimpleResult(3, $"插入盘点差异表失败");
                }
                return NewSimpleResult(0, "盘点差异完成");
            }
            catch (Exception ex) {
                return NewSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        internal static string GenerateNo(string snType, string prefix) {
            var id = SYSHelper.GetSerialNumber(snType, prefix);
            var date = DateTime.Now.ToString("yyMMdd");
            return $"TN{date}{id.ToString().PadLeft(4, '0')}";
        }
        /// <summary>
        /// 盘点理货出库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult CheckOutbound(CheckOutboundInfo model) {
            var taskName = TaskName.盘点理货出库;
            var db = new SqlHelper<object>().GetInstance();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == "SFQ");
                if (startLoc == null) {
                    return NewSimpleResult(2, $"起点位置 {model.startLoc} 不符合出库条件");
                }
                var locCntrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.startLoc);
                if (locCntrRel == null) {
                    return NewSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可回库的物料");
                }
                // 终点位置:货架(没有货物,没有锁)
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                if (endLoc == null) {
                    return NewSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
                }
                var cntID = locCntrRel.S_CNTR_CODE;
                var task = WCSHelper.BuildTask(startLoc, endLoc, cntID, taskName);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货位 {endLoc.S_CODE}");
                    }
                    if (db.Updateable<TN_Location>(endLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                    }
                    if (db.Insertable<TN_Task>(task).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                    }
                    tran.CommitTran();
                    return NewSimpleResult(0,
                        $"生成 {taskName} 成功,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                }
            }
            catch (Exception ex) {
                return NewSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 盘点理货回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        internal static SimpleResult CheckInbound(CheckInboundInfo model) {
            var taskName = TaskName.盘点理货回库;
            var db = new SqlHelper<object>().GetInstance();
            try {
                // 起点位置:取放货区(有货物、没有锁、已启用)
                var startLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.startLoc && a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y" && a.S_AREA_CODE == "SFQ");
                if (startLoc == null) {
                    return NewSimpleResult(2, $"起点位置 {model.startLoc} 不符合回库条件");
                }
                var locCntrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == model.startLoc);
                if (locCntrRel == null) {
                    return NewSimpleResult(3, $"起点位置 {model.startLoc} 没有绑定容器,无可回库的物料");
                }
                // 终点位置:货架(没有货物,没有锁)
                var endLoc = db.Queryable<TN_Location>().First(a => a.S_CODE == model.endLoc && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                if (endLoc == null) {
                    return NewSimpleResult(4, $"终点位置 {model.endLoc} 不具备放货条件");
                }
                var cntID = locCntrRel.S_CNTR_CODE;
                var task = WCSHelper.BuildTask(startLoc, endLoc, cntID, taskName);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货位 {endLoc.S_CODE}");
                    }
                    if (db.Updateable<TN_Location>(endLoc).UpdateColumns(it => new {
                        it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                    }
                    if (db.Insertable<TN_Task>(task).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return NewSimpleResult(500,
                            $"生成 {taskName} 失败,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                    }
                    tran.CommitTran();
                    return NewSimpleResult(0,
                        $"生成 {taskName} 成功,容器号 {cntID} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                }
            }
            catch (Exception ex) {
                return NewSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        public static ErpResult InboundDataSync(InboundDataSyncInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            try {
            }
            catch (Exception ex) {
                return BuildErpResult(1, ex.Message);
            }
            return BuildErpResult(0, null);
        }
        public static ErpResult OutboundDataSync(OutboundDataSyncInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            try {
            }
            catch (Exception ex) {
                return BuildErpResult(1, ex.Message);
            }
            return BuildErpResult(1, null);
        }
    }
}
api/ApiModel.cs
New file
@@ -0,0 +1,481 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace HH.WCS.Mobox3.AnGang.api
{
    /// <summary>
    /// 通用model
    /// </summary>
    public class ApiModel
    {
        #region mobox 相关
        public class SimpleResult {
            public int resultCode { get; set; }
            public string resultMsg { get; set; }
            public List<object> result { get; set; } = new List<object>();
        }
        public static SimpleResult NewSimpleResult(int code, string message) {
            return new SimpleResult { resultCode = code, resultMsg = message };
        }
        #endregion
        /// <summary>
        /// hosttoagv上报任务状态
        /// </summary>
        public class AgvTaskState {
            public int state { get; set; }
            public string task_no { get; set; }
            public string forklift_no { get; set; }
            /// <summary>
            /// 安全门编号
            /// </summary>
            public string lock_no { get; set; }
            public string ext_data { get; set; }
        }
        public class SafetyInteractionInfo {
            public int station_id { get; set; }
            /// <summary>
            /// 请求上线/下线的的站台库位名称,例如work6、work8
            /// </summary>
            public string station_name { get; set; }
            /// <summary>
            /// 请求码
            /// </summary>
            public string apply_code { get; set; }
            public string task_no { set; get; }
        }
        public class orderStatusReportParme {
            /// <summary>
            /// 订单ID
            /// </summary>
            public int orderID { get; set; }
            /// <summary>
            /// 订单名
            /// </summary>
            public string orderName { get; set; }
            /// <summary>
            /// 订单状态
            /// </summary>
            public string orderStatus { get; set; }
            /// <summary>
            /// agv车号列表
            /// </summary>
            public string agvIDList { get; set; }
            /// <summary>
            /// 优先级
            /// </summary>
            public string priority { get; set; }
            /// <summary>
            /// 订单当前的目的地
            /// </summary>
            public string currentDes { get; set; }
            /// <summary>
            /// 当前指令
            /// </summary>
            public string currentCmd { get; set; }
            /// <summary>
            /// 错误码
            /// </summary>
            public int errorCode { get; set; }
            /// <summary>
            /// 订单的截至时间
            /// </summary>
            public string deadLine { get; set; }
            /// <summary>
            /// 订单的创建时间
            /// </summary>
            public string createdTime { get; set; }
            /// <summary>
            /// 额外信息1
            /// </summary>
            public string extraInfo1 { get; set; }
            /// <summary>
            /// 额外信息2
            /// </summary>
            public string extraInfo2 { get; set; }
        }
        /// <summary>
        /// 返回给hosttoagv
        /// </summary>
        public class ReturnResult {
            public int ResultCode { get; set; }
            public string ResultMsg { get; set; }
        }
        /// <summary>
        /// 返回给GZ
        /// </summary>
        public class GzResult {
            public int resultCode { get; set; }
            public string msg { get; set; }
            public int orderID { get; set; }
        }
    }
    public class OtherModel {
        public class InboundInfo {
            /// <summary>
            /// 起点货位
            /// </summary>
            [JsonProperty("StartLoc")]
            public string StartLoc { get; set; }
            /// <summary>
            /// 终点货架(可选)
            /// </summary>
            [JsonProperty("Nrow")]
            public string Row { get; set; }
        }
        public class SelectLocationInfo {
            /// <summary>
            /// AGV小车号:NOTE 后期可能省略,因为只有一辆车
            /// </summary>
            public string forklift_no { get; set; }
            public string endLoc { get; set; }
        }
        /// <summary>
        /// 产品部分回库信息
        /// </summary>
        public class PartInboundInfo {
            /// <summary>
            /// 起点位置
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 终点位置
            /// </summary>
            public string endLoc { get; set; }
        }
        /// <summary>
        /// 产品部分出库信息
        /// </summary>
        public class PartOutboundInfo {
            /// <summary>
            /// 起点位置
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 终点位置
            /// </summary>
            public string endLoc { get; set; }
        }
        public class CreateCountPlanInfo {
            public string countType { get; set; }
            public string targetId { get; set; }
        }
        public class CreateCountOrderInfo {
            public string planId { get; set; }
        }
        public class CountProductInfo {
            public string cntrCode { get; set; }
            public float qty { get; set; }
        }
        /// <summary>
        /// 盘点理货出库信息
        /// </summary>
        public class CheckOutboundInfo {
            /// <summary>
            /// 起点位置
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 终点位置
            /// </summary>
            public string endLoc { get; set; }
        }
        /// <summary>
        /// 盘点理货回库信息
        /// </summary>
        public class CheckInboundInfo {
            /// <summary>
            /// 起点位置
            /// </summary>
            public string startLoc { get; set; }
            /// <summary>
            /// 终点位置
            /// </summary>
            public string endLoc { get; set; }
        }
        public class ErpResult {
            /// <summary>
            /// 接口反馈码
            /// </summary>
            public int errCode { get; set; }
            /// <summary>
            /// 错误说明
            /// </summary>
            public string errMsg { get; set; }
        }
        public static ErpResult BuildErpResult(int code, string message, bool printLog = true) {
            if (printLog) {
                LogHelper.Info(message);
            }
            return new ErpResult { errCode = code, errMsg = message };
        }
        /// <summary>
        /// 入库数据同步信息
        /// </summary>
        public class InboundDataSyncInfo {
            /// <summary>
            /// 库存明细(列表)
            /// </summary>
            public List<StockTransaction> stockTransactions { get; set; }
            /// <summary>
            /// 总记录数
            /// </summary>
            public string totalRecords { get; set; }
            /// <summary>
            /// 数据生成时间戳
            /// </summary>
            public string timestamp { get; set; }
        }
        /// <summary>
        /// 库存明细信息
        /// </summary>
        public class StockTransaction {
            /// <summary>
            /// 储位码
            /// </summary>
            public string locationCode { get; set; }
            /// <summary>
            /// 库存明细交易号
            /// </summary>
            public string stockTransactionId { get; set; }
            /// <summary>
            /// 物料编码
            /// </summary>
            public string itemCode { get; set; }
            /// <summary>
            /// 物料名称
            /// </summary>
            public string itemName { get; set; }
            /// <summary>
            /// 物料短描述
            /// </summary>
            public string itemShortDesc { get; set; }
            /// <summary>
            /// 库存数量
            /// </summary>
            public string stockQuantity { get; set; }
            /// <summary>
            /// 入库数量
            /// </summary>
            public string inQuantity { get; set; }
            /// <summary>
            /// 库存总价
            /// </summary>
            public string totalPrice { get; set; }
            /// <summary>
            /// 入库时间
            /// </summary>
            public string stockInTime { get; set; }
            /// <summary>
            /// 保管员
            /// </summary>
            public string storeKeeper { get; set; }
            /// <summary>
            /// 产线部门代码
            /// </summary>
            public string lineCode { get; set; }
            /// <summary>
            /// 送货单行号
            /// </summary>
            public string deliveryItemNo { get; set; }
            /// <summary>
            /// 供应商名称
            /// </summary>
            public string supplierName { get; set; }
            /// <summary>
            /// 库存责任人姓名
            /// </summary>
            public string inventoryManager { get; set; }
            /// <summary>
            /// 备用字段1
            /// </summary>
            public string ext1 { get; set; }
            /// <summary>
            /// 备用字段2
            /// </summary>
            public string ext2 { get; set; }
            /// <summary>
            /// 备用字段3
            /// </summary>
            public string ext3 { get; set; }
            /// <summary>
            /// 备用字段4
            /// </summary>
            public string ext4 { get; set; }
            /// <summary>
            /// 备用字段5
            /// </summary>
            public string ext5 { get; set; }
        }
        /// <summary>
        /// 出库发料同步信息
        /// </summary>
        public class OutboundDataSyncInfo {
            /// <summary>
            /// 发料记录明细列表
            /// </summary>
            public List<MaterialIssue> materialIssues { get; set; }
            /// <summary>
            /// 总记录数
            /// </summary>
            public string totalRecords { get; set; }
            /// <summary>
            /// 数据生成时间戳
            /// </summary>
            public string timestamp { get; set; }
        }
        /// <summary>
        /// 发料记录明细信息
        /// </summary>
        public class MaterialIssue {
            /// <summary>
            /// 储位码
            /// </summary>
            public string locationCode { get; set; }
            /// <summary>
            /// 领用单号
            /// </summary>
            public string withdrawalOrderNo { get; set; }
            /// <summary>
            /// 物料编码
            /// </summary>
            public string itemCode { get; set; }
            /// <summary>
            /// 物料名称
            /// </summary>
            public string itemName { get; set; }
            /// <summary>
            /// 物料短描述
            /// </summary>
            public string itemShortDesc { get; set; }
            /// <summary>
            /// 实发数量
            /// </summary>
            public string actualIssuedQty { get; set; }
            /// <summary>
            /// 实发金额
            /// </summary>
            public string issuedAmount { get; set; }
            /// <summary>
            /// 供应商名称
            /// </summary>
            public string supplierName { get; set; }
            /// <summary>
            /// 实发人
            /// </summary>
            public string issuer { get; set; }
            /// <summary>
            /// 发料日期
            /// </summary>
            public string issueDate { get; set; }
            /// <summary>
            /// 保管员
            /// </summary>
            public string storeKeeper { get; set; }
            /// <summary>
            /// 产线部门代码
            /// </summary>
            public string lineCode { get; set; }
            /// <summary>
            /// 批次
            /// </summary>
            public string batchNo { get; set; }
            /// <summary>
            /// 备用字段1
            /// </summary>
            public string ext1 { get; set; }
            /// <summary>
            /// 备用字段2
            /// </summary>
            public string ext2 { get; set; }
            /// <summary>
            /// 备用字段3
            /// </summary>
            public string ext3 { get; set; }
            /// <summary>
            /// 备用字段4
            /// </summary>
            public string ext4 { get; set; }
            /// <summary>
            /// 备用字段5
            /// </summary>
            public string ext5 { get; set; }
        }
    }
}
api/DebugController.cs
New file
@@ -0,0 +1,320 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using HH.WCS.Mobox3.AnGang.dispatch;
using HH.WCS.Mobox3.AnGang.wms;
using HH.WCS.Mobox3.AnGang.models;
using Newtonsoft.Json;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
using HH.WCS.Mobox3.AnGang.util;
namespace HH.WCS.Mobox3.AnGang.api {
    /// <summary>
    /// 测试用,如果项目中要和设备对接,前期设备无法测试,用接口模拟
    /// </summary>
    [RoutePrefix("api")]
    public class DebugController : System.Web.Http.ApiController
    {
        /// <summary>
        /// AGV状态一键回报1462-国自
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("AGVSeriesReports")]
        public GzResults AGVSeriesReports(UpdateTaskState model) {
            GzResults gzResults = new GzResults();
            gzResults.GzResultList = new List<GzResult>();
            var orderStatus = new orderStatusReportParme() {
                orderName = model.TaskID,
                agvIDList = model.ForkliftNo,
                orderStatus = "waiting",
            };
            var temp1 = GZRobot.orderStatusReport(orderStatus);
            gzResults.GzResultList.Add(temp1);
            orderStatus.orderStatus = "source_finish";
            var temp2 = GZRobot.orderStatusReport(orderStatus);
            gzResults.GzResultList.Add(temp2);
            orderStatus.orderStatus = "dest_finish";
            var temp3 = GZRobot.orderStatusReport(orderStatus);
            gzResults.GzResultList.Add(temp3);
            orderStatus.orderStatus = "finish";
            var temp4 = GZRobot.orderStatusReport(orderStatus);
            gzResults.GzResultList.Add(temp4);
            return gzResults;
        }
        /// <summary>
        /// AGV状态一键回报14-国自
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("AGVSeriesReports-14")]
        public GzResults AGVSeriesReports14(UpdateTaskState model) {
            GzResults gzResults = new GzResults();
            gzResults.GzResultList = new List<GzResult>();
            var orderStatus = new orderStatusReportParme() {
                orderName = model.TaskID,
                agvIDList = model.ForkliftNo,
                orderStatus = "waiting",
            };
            var temp1 = GZRobot.orderStatusReport(orderStatus);
            gzResults.GzResultList.Add(temp1);
            orderStatus.orderStatus = "source_finish";
            var temp2 = GZRobot.orderStatusReport(orderStatus);
            gzResults.GzResultList.Add(temp2);
            return gzResults;
        }
        /// <summary>
        /// AGV状态一键回报62-国自
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("AGVSeriesReports-62")]
        public GzResults AGVSeriesReports62(UpdateTaskState model) {
            GzResults gzResults = new GzResults();
            gzResults.GzResultList = new List<GzResult>();
            var orderStatus = new orderStatusReportParme() {
                orderName = model.TaskID,
                agvIDList = model.ForkliftNo,
                orderStatus = "dest_finish",
            };
            var temp3 = GZRobot.orderStatusReport(orderStatus);
            gzResults.GzResultList.Add(temp3);
            orderStatus.orderStatus = "finish";
            var temp4 = GZRobot.orderStatusReport(orderStatus);
            gzResults.GzResultList.Add(temp4);
            return gzResults;
        }
        /// <summary>
        /// 初始化数据库
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("CreateDatabase")]
        public string CreateDatabase(CoverInfo model) {
            try {
                var db = new SqlHelper<object>().GetInstance();
                var cover = model.IsCover;
                var entityTypes = new Type[] {
                    typeof(TN_CAR_IN),
                    typeof(TN_CG_Detail),
                    typeof(TN_Container),
                    typeof(TN_Loc_Container),
                    typeof(TN_Location),
                    typeof(TN_Task),
                    typeof(TN_Task_Action),
                    typeof(SYSHelper.OI_SYS_MAXID),
                };
                using (var tran = db.Ado.UseTran()) {
                    if (cover) {
                        // 删除所有表(按依赖关系倒序)
                        var tables = db.DbMaintenance.GetTableInfoList();
                        foreach (var table in tables.OrderByDescending(t => t.Name)) {
                            db.DbMaintenance.DropTable(table.Name);
                        }
                        // 创建新表
                        db.CodeFirst.InitTables(entityTypes);
                        //db.CodeFirst.BackupTable().InitTables(entityTypes);
                    }
                    else {
                        db.CodeFirst.InitTables(entityTypes);
                    }
                    tran.CommitTran();
                }
            }
            catch (Exception ex) {
                LogHelper.Info($"发生了异常");
                return "初始化数据库错误" + ex.Message;
            }
            return "成功";
        }
        /// <summary>
        /// DEBUG:插入货位、容器、货品信息
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("InsertLocCntrCg")]
        public string InsertLocCntrCg(LocCntrCg locCntrCg) {
            var db = new SqlHelper<object>().GetInstance();
            try {
                using (var tran = db.UseTran()) {
                    LogHelper.Info("LogCntrCg:" + JsonConvert.SerializeObject(locCntrCg));
                    if (string.IsNullOrEmpty(locCntrCg.LocCode)) {
                        return "参数非法";
                    }
                    var loc = db.Queryable<TN_Location>().First(a => a.S_CODE == locCntrCg.LocCode);
                    if (loc == null) {
                        var newLoc = new TN_Location {
                            S_CODE = locCntrCg.LocCode,
                            S_AREA_CODE = locCntrCg.LocArea ?? ""
                        };
                        if (db.Insertable<TN_Location>(newLoc).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info($"插入位置{locCntrCg.LocCode}失败");
                            return "插入失败";
                        }
                        loc = newLoc;
                    }
                    //if (loc.N_CURRENT_NUM == 0) {
                    //    loc.N_CURRENT_NUM = 1;
                    //    if (db.Updateable<TN_Location>(loc).UpdateColumns(
                    //        it => new { it.N_CURRENT_NUM, it.T_MODIFY }).ExecuteCommand() <= 0) {
                    //        tran.RollbackTran();
                    //        LogHelper.Info($"修改位置{locCntrCg.LocCode}失败");
                    //        continue;
                    //    }
                    //}
                    if (string.IsNullOrEmpty(locCntrCg.CntrCode)) {
                        tran.CommitTran();
                        LogHelper.Info("容器号为空,不再读取后面的数据");
                        return "容器号为空,不再读取后面的数据";
                    }
                    var locCntrRel = db.Queryable<TN_Loc_Container>().First(a => a.S_LOC_CODE == locCntrCg.LocCode
                        && a.S_CNTR_CODE == locCntrCg.CntrCode);
                    if (locCntrRel == null) {
                        var newLocCntrRel = new TN_Loc_Container {
                            S_LOC_CODE = locCntrCg.LocCode,
                            S_CNTR_CODE = locCntrCg.CntrCode
                        };
                        loc.N_CURRENT_NUM = 1;
                        if (db.Insertable<TN_Loc_Container>(newLocCntrRel).ExecuteCommand() <= 0
                            && db.Updateable<TN_Location>(loc).UpdateColumns(c => c.N_CURRENT_NUM).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info($"插入位置托盘关系{locCntrCg.LocCode}-{locCntrCg.CntrCode}失败");
                            return "插入失败";
                        }
                    }
                    if (string.IsNullOrEmpty(locCntrCg.ItemCode)) {
                        tran.CommitTran();
                        LogHelper.Info("物料号为空,不再读取后面的数据");
                        return "物料号为空,不再读取后面的数据";
                    }
                    var cgDetail = db.Queryable<TN_CG_Detail>().First(a => a.S_CNTR_CODE == locCntrCg.CntrCode
                        && a.S_ITEM_CODE == locCntrCg.ItemCode);
                    if (cgDetail == null) {
                        var locList = new List<TN_CG_Detail>();
                        locList.Add(new TN_CG_Detail { S_CNTR_CODE = locCntrCg.CntrCode, S_ITEM_CODE = locCntrCg.ItemCode, S_BATCH_NO = locCntrCg.BatchNo ?? "" });
                        if (db.Insertable<TN_CG_Detail>(locList).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info($"插入托盘物料关系{locCntrCg.CntrCode}-{locCntrCg}失败");
                            return "插入失败";
                        }
                    }
                    tran.CommitTran();
                }
                return "插入数据成功";
            }
            catch (Exception ex) {
                return $"{ex.Message}";
            }
        }
        [HttpPost]
        [Route("SetTaskWeight")]
        public string SetTaskWeight(SetTaskWeightInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            var cgDetail = db.Queryable<TN_CG_Detail, TN_Task>((d, t) => d.S_CNTR_CODE == t.S_CNTR_CODE)
                .Where((d, t) => t.S_CODE == model.TaskNo).First();
            if (cgDetail == null) {
                return "找不到对应的物料信息";
            }
            cgDetail.F_QTY = model.Weight;
            try {
                if (db.Updateable<TN_CG_Detail>(cgDetail).UpdateColumns(it => it.F_QTY)
                    .ExecuteCommand() <= 0) {
                    return "修改失败";
                }
                return "修改成功";
            }
            catch (Exception ex) {
                return ex.Message;
            }
        }
    }
    public class ReturnResults {
        public List<ReturnResult> ResultList { set; get; }
    }
    public class GzResults {
        public List<GzResult> GzResultList { set; get; }
    }
    public class LocCntrCg {
        public string LocCode { get; set; }
        public string LocArea { get; set; }
        public string CntrCode { get; set; }
        public string ItemCode { get; set; }
        public string BatchNo { get; set; }
    }
    /// <summary>
    /// 模拟 AGV 传递信号,用于更改任务状态
    /// </summary>
    public class UpdateTaskState {
        /// <summary>
        /// 任务ID
        /// </summary>
        public string TaskID { set; get; }
        /// <summary>
        /// AGV 小车号
        /// </summary>
        public string ForkliftNo { set; get; }
        /// <summary>
        /// AGV 下一个状态
        /// </summary>
        public int NextState { set; get; }
    }
    public class CoverInfo {
        public bool IsCover { set; get; } = true;
    }
    public class SetTaskWeightInfo {
        public string TaskNo { set; get; }
        public float Weight { set; get; }
    }
}
api/ErpController.cs
File was renamed from Controllers/ErpController.cs
@@ -1,11 +1,8 @@
using System.Web.Http;
using HH.WCS.Mobox3.AnGang.Services;
using static HH.WCS.Mobox3.AnGang.api.OtherModel;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.ErpRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.ErpResponse;
namespace HH.WCS.Mobox3.AnGang.Controllers {
namespace HH.WCS.Mobox3.AnGang.api {
    /// <summary>
    /// ERP 调用的接口
    /// </summary>
@@ -19,7 +16,7 @@
        [HttpPost]
        [Route("InboundDataSync")]
        public static ErpResult InboundDataSync(InboundDataSyncInfo model) {
            return ErpService.InboundDataSync(model);
            return ApiHelper.InboundDataSync(model);
        }
        /// <summary>
@@ -30,7 +27,7 @@
        [HttpPost]
        [Route("OutboundDataSync")]
        public static ErpResult OutboundDataSync(OutboundDataSyncInfo model) {
            return ErpService.OutboundDataSync(model);
            return ApiHelper.OutboundDataSync(model);
        }
    }
}
api/MoboxController.cs
New file
@@ -0,0 +1,115 @@
using System.Web.Http;
using Newtonsoft.Json;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
using static HH.WCS.Mobox3.AnGang.api.OtherModel;
namespace HH.WCS.Mobox3.AnGang.api {
    /// <summary>
    /// Mobox3 调用,脚本中调用
    /// </summary>
    [RoutePrefix("api")]
    public class MoboxController : ApiController {
        /// <summary>
        /// 货品入库(PDA)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Inbound")]
        public SimpleResult Inbound(InboundInfo model) {
            LogHelper.Info("触发API:产品入库(PDA)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.Inbound(model);
        }
        /// <summary>
        /// PDA选择终点货位
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("SelectLocation")]
        public SimpleResult SelectLocation(SelectLocationInfo model) {
            LogHelper.Info("触发API:PDA选择终点货位" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.SelectLocation(model);
        }
        /// <summary>
        /// 产品部分出库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("PartOutbound")]
        public SimpleResult PartOutbound(PartOutboundInfo model) {
            LogHelper.Info("触发API:产品部分出库(WMS)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.PartOutbound(model);
        }
        /// <summary>
        /// 产品部分回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("PartInbound")]
        public SimpleResult PartInbound(PartInboundInfo model) {
            LogHelper.Info("触发API:产品部分回库(WMS)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.PartInbound(model);
        }
        /// <summary>
        /// 创建盘点计划单(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CreateCountPlan")]
        public SimpleResult CreateCountPlan(CreateCountPlanInfo model) {
            LogHelper.Info("触发API:创建盘点计划单(WMS)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CreateCountPlan(model);
        }
        /// <summary>
        /// 创建盘点单(PDA)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CreateCountOrder")]
        public SimpleResult CreateCountOrder(CreateCountOrderInfo model) {
            LogHelper.Info("触发API:创建盘点单(PDA)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CreateCountOrder(model);
        }
        public SimpleResult CountProduct(CountProductInfo model) {
            LogHelper.Info("触发API:盘点理货(PDA)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CountProduct(model);
        }
        /// <summary>
        /// 盘点理货出库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CheckOutbound")]
        public SimpleResult CheckOutbound(CheckOutboundInfo model) {
            LogHelper.Info("触发API:盘点理货出库(WMS)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CheckOutbound(model);
        }
        /// <summary>
        /// 盘点理货回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CheckInbound")]
        public SimpleResult CheckInbound(CheckInboundInfo model) {
            LogHelper.Info("触发API:盘点理货回库(WMS)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CheckInbound(model);
        }
    }
}
api/WmsController.cs
File was renamed from Controllers/WmsController.cs
@@ -3,9 +3,9 @@
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Web.Http;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
namespace HH.WCS.Mobox3.AnGang.Controllers
namespace HH.WCS.Mobox3.AnGang.api
{
    /// <summary>
    /// 第三方调用的接口
config/config.json
@@ -2,7 +2,7 @@
    "WebApiUrl": "http://127.0.0.1:8901",
    "RCSApiUrl": "http://127.0.0.1:6001",
    "NDCApiUrl": "http://127.0.0.1:5201/api/order/",
    "SqlServer": "Data Source=192.168.1.144;Initial Catalog=YinKouAnGan;User ID=hhuser;Password=Am123123",
    "SqlServer": "Data Source=(local);Initial Catalog=AnGangTest;User ID=sa;Password=123456",
    "TCPServerIP": "127.0.0.1",
    "TCPServerPort": 8085,
    "Areas": [
@@ -15,7 +15,7 @@
            "Codes": [ "HJQ" ]
        }
    ],
    "Snap": [
    "Snaps": [
        {
            "Ip": "172.23.8.95",
            "Port": 37777,
core/Monitor.cs
New file
@@ -0,0 +1,159 @@

using HH.WCS.Mobox3.AnGang.models;
using HH.WCS.Mobox3.AnGang.process;
using HH.WCS.Mobox3.AnGang.util;
using HH.WCS.Mobox3.AnGang.wms;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace HH.WCS.Mobox3.AnGang.core {
    /// <summary>
    /// 定时轮询任务
    /// </summary>
    public class Monitor
    {
        public static void CheckCountOrder() {
            var taskName = TaskName.盘点理货出库;
            var db = new SqlHelper<object>().GetInstance();
            var info = "";
            try {
                var orderList = db.Queryable<TN_Count_Order>()
                    .Where(c => c.N_B_STATE == 1)
                    .OrderBy(c => c.T_CREATE, SqlSugar.OrderByType.Asc)
                    .ToList();
                if (orderList.Count == 0) {
                    LogHelper.Info("轮询--出库--暂无待执行的Order");
                    return;
                }
                var detailList = new List<TN_Count_CG_Detail>();
                foreach (var order in orderList) {
                    var doingCount = db.Queryable<TN_Count_CG_Detail>()
                        .Count(d => d.S_COUNT_NO == order.S_COUNT_NO && d.N_B_STATE >= 2); // 执行中
                    var allCount = db.Queryable<TN_Count_CG_Detail>()
                        .Count(d => d.S_COUNT_NO == order.S_COUNT_NO);
                    LogHelper.Info($"轮询--{taskName}--统计{taskName}单'{order.S_COUNT_NO}'任务已下发:{doingCount}/{allCount}");
                    if (doingCount == allCount) {
                        order.N_B_STATE = 2; // 所有任务都已执行
                        db.Updateable<TN_Count_Order>(order).UpdateColumns(it => new { it.N_B_STATE }).ExecuteCommand();
                        continue;
                    }
                    var lastDetail = db.Queryable<TN_Count_CG_Detail>()
                        .Where(d => d.S_COUNT_NO == order.S_COUNT_NO && d.N_B_STATE == 2) // TODO 或者改成查task
                        .First();
                    if (lastDetail != null) {
                        LogHelper.Info($"轮询--{taskName}--{taskName}单'{order.S_COUNT_NO}'上一个任务仍在进行中:"
                            + JsonConvert.SerializeObject(lastDetail));
                        continue;
                    }
                    var outboundDetail = db.Queryable<TN_Count_CG_Detail>()
                        .Where(a => a.S_COUNT_NO == order.S_COUNT_NO && a.N_B_STATE == 1) // 已下发
                        .First();
                    if (outboundDetail != null) {
                        LogHelper.Info($"轮询--{taskName}--");
                        continue;
                    }
                    detailList.Add(outboundDetail);
                }
                if (detailList.Count == 0) {
                    return;
                }
                var startLocList = new List<TN_Location>();
                var endLocList = new List<TN_Location>();
                var taskList = new List<TN_Task>();
                foreach (var detail in detailList) {
                    var startLoc = db.Queryable<TN_Location>()
                        .LeftJoin<TN_Loc_Container>((l, c) => l.S_CODE == c.S_LOC_CODE)
                        .Where((l, c) => c.S_CNTR_CODE == detail.S_CNTR_CODE)
                        .First();
                    if (startLoc == null) {
                        LogHelper.Info($"轮询--出库:没有找到合适的起点货位!");
                        continue;
                    }
                    var endLoc = db.Queryable<TN_Location>()
                        .Where(a => a.S_AREA_CODE == "SFQ")
                        .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y")
                        .Where(a => a.N_CURRENT_NUM == 0).First();
                    if (endLoc == null) {
                        LogHelper.Info($"轮询--出库:没有找到合适的终点货位!S_NO为 '{detail.S_COUNT_NO}'");
                        continue;
                    }
                    detail.N_B_STATE = 2;
                    var cntId = detail.S_CNTR_CODE;
                    var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName);
                    LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                    LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                    using (var tran = db.Ado.UseTran()) {
                        if (db.Updateable<TN_Count_CG_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info($"轮询--出库--修改明细表状态为完成失败!");
                        }
                        if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
                            it.N_LOCK_STATE,
                            it.S_LOCK_STATE,
                            it.S_LOCK_OP,
                            it.T_MODIFY
                        }).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            info = $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货位 {endLoc.S_CODE}";
                            LogHelper.Info(info);
                            continue;
                        }
                        if (db.Updateable<TN_Location>(endLoc).UpdateColumns(it => new {
                            it.N_LOCK_STATE,
                            it.S_LOCK_STATE,
                            it.S_LOCK_OP,
                            it.T_MODIFY
                        }).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            info = $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货位 {endLoc.S_CODE}";
                            LogHelper.Info(info);
                            continue;
                        }
                        if (db.Insertable<TN_Task>(task).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            info = $"生成 {taskName} 失败,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货位 {endLoc.S_CODE}";
                            LogHelper.Info(info);
                            continue;
                        }
                        tran.CommitTran();
                        info = $"生成 {taskName} 成功,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货位 {endLoc.S_CODE}";
                        LogHelper.Info(info);
                        continue;
                    }
                }
            }
            catch (Exception ex) {
                info = $"发生了异常:{ex.Message}";
                LogHelper.Info(info);
            }
        }
    }
}
core/WCSCore.cs
File was renamed from Services/AgvService.cs
@@ -1,47 +1,34 @@
using HH.WCS.Mobox3.AnGang.Helpers;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.device;
using HH.WCS.Mobox3.AnGang.dispatch;
using HH.WCS.Mobox3.AnGang.models;
using HH.WCS.Mobox3.AnGang.process;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
using HH.WCS.Mobox3.AnGang.wms;
using HH.WCS.Mobox3.AnGang.util;
using static HH.WCS.Mobox3.AnGang.Dtos.Request.AgvRequest;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.AgvResponse;
using HH.WCS.Mobox3.AnGang.Consts;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.Devices;
namespace HH.WCS.Mobox3.AnGang.Services {
    public class AgvService {
namespace HH.WCS.Mobox3.AnGang.core
{
    internal class WCSCore
    {
        public static ReturnResult OperateAgvTaskStatus(AgvTaskState model) {
            var result = new ReturnResult();
            try {
                switch (model.state) {
                    case 1023:
                        break;
                    case 1025:
                        break;
                    case 1012:
                        break;
                    case 1004:
                        break;
                    case 1103:
                        break;
                    default:
                        // AGV 执行任务的逻辑处理
                        if (!AgvTaskProcessOk(model)) {
                            // 执行不OK,说明没有找到任务
                            result.ResultCode = 1;
                            result.ResultMsg = $"根据Model.No未找到对应的任务,{model.task_no}";
                            LogHelper.Info(result.ResultMsg, "API");
                            return result;
                        }
                        break;
                if (model.state > 0 && model.state < 1000) {
                    // AGV 执行任务的逻辑处理
                    if (!AgvTaskProcessOk(model)) {
                        // 执行不OK,说明没有找到任务
                        result.ResultCode = 1;
                        result.ResultMsg = $"根据Model.No未找到对应的任务,{model.task_no}";
                        LogHelper.Info(result.ResultMsg, "API");
                        return result;
                    }
                }
                result.ResultCode = 0;
@@ -69,48 +56,48 @@
            if (model.state > 7) {
                //安全请求等
                TaskHelper.OperateReq(model.task_no, model.state, model.forklift_no, model.ext_data);
                TaskProcess.OperateReq(model.task_no, model.state, model.forklift_no, model.ext_data);
                return true;
            }
            // AGV 任务 134562(7) 状态处理
            switch (model.state) {
                case AgvStateCode.执行:
                case 1: // 执行
                    WCSHelper.Begin(TN_Task, model.forklift_no); // 已推送的任务的状态改成执行
                    break;
                case AgvStateCode.开始取货:
                case 3: // 开始取货
                    WCSHelper.UpdateStatus(TN_Task, "开始取货"); // 任务状态改成开始取货
                    break;
                case AgvStateCode.取货完成:
                case 4: // 取货完成
                    WCSHelper.UpdateStatus(TN_Task, "取货完成"); // 任务状态改成取货完成
                    var captureTask = Task.Run(() => {
                        if (TN_Task.S_TYPE == TaskName.产品入库 || TN_Task.S_TYPE == TaskName.产品部分回库) {
                    if (TN_Task.S_TYPE == TaskName.产品入库 || TN_Task.S_TYPE == TaskName.产品部分回库) {
                        var captureTask = Task.Run(() => {
                            CapturePic(TN_Task);
                        }
                    });
                        });
                    }
                    var setEndLocTask = Task.Run(() => {
                        // 只要任务为产品入库(PDA),就需要重新指定终点(默认endLoc为"")
                        if (TN_Task.S_TYPE == TaskName.产品入库) {
                    if (TN_Task.S_TYPE == TaskName.产品入库) {
                        var setEndLocTask = Task.Run(() => {
                            // 只要任务为产品入库(PDA),就需要重新指定终点(默认endLoc为"")
                            SetEndLoc(TN_Task);
                        }
                    });
                        });
                    }
                    TaskHelper.OperateStatus(TN_Task, 4); // 起点容器货位解绑,解锁起点
                    TaskProcess.OperateStatus(TN_Task, 4); // 起点容器货位解绑,解锁起点
                    break;
                case AgvStateCode.开始卸货:
                case 5: // 开始卸货
                    WCSHelper.UpdateStatus(TN_Task, "开始卸货"); // 任务状态改成开始卸货
                    break;
                case AgvStateCode.卸货完成:
                case 6: // 卸货完成
                    WCSHelper.UpdateStatus(TN_Task, "卸货完成"); // 任务状态改成卸货完成
                    TaskHelper.OperateStatus(TN_Task, 6); // 终点容器货位绑定,解锁终点
                    TaskProcess.OperateStatus(TN_Task, 6); // 终点容器货位绑定,解锁终点
                    break;
                case AgvStateCode.完成:
                case 2: // 完成
                    WCSHelper.End(TN_Task); // 任务状态改成结束
                    break;
                case AgvStateCode.异常:
                    TaskHelper.OperateStatus(TN_Task, 7); // 异常处理
                case 7: // 异常
                    TaskProcess.OperateStatus(TN_Task, 7); // 异常处理
                    WCSHelper.Fail(TN_Task); // 任务状态改成错误
                    break;
            }
@@ -122,7 +109,7 @@
        }
        public static void CapturePic(TN_Task model) {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var filepath = SnapManager.GetCapturePicturePath();
            if (string.IsNullOrEmpty(filepath)) {
@@ -140,7 +127,7 @@
        }
        public static void SetEndLoc(TN_Task tn_task) {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var endLoc = db.Queryable<TN_Location>()
                .First(a => a.S_CODE == tn_task.S_END_LOC);
@@ -218,45 +205,58 @@
                //};
                //GZRobot.UpdateInteractInfo(request);
                using (var trans = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                        .ExecuteCommand() > 0) {
                        //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改成功,修改终点货位为 0空");
                    }
                    else {
                        trans.RollbackTran();
                        LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改失败,修改终点货位为 0空");
                    }
                    //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                    LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改成功,修改终点货位为 0空");
                }
                else {
                    LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改失败,修改终点货位为 0空");
                }
            }
            else {
                // 找到合适的货位,推送
                tn_task.S_END_LOC = endLoc.S_CODE;
                using (var trans = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                        .ExecuteCommand() > 0) {
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改成功,终点货架为 {endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                    }
                    else {
                        trans.RollbackTran();
                        LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改失败,终点货架为 {endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                    }
                    LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                    LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改成功,终点货架为 {endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                }
                else {
                    LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改失败,终点货架为 {endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                }
            }
        }
        /// <summary>
        /// 任务分发,根据调度类型发给不同的调度系统
        /// </summary>
        internal static void Dispatch()
        {
            //查询任务
            //获取所有等待的任务
            var list = WCSHelper.GetWaitingTaskList();
            LogHelper.Info("等待任务信息" + JsonConvert.SerializeObject(list), "API");
            if (list.Count > 0)
            {
                list.ForEach(task =>
                {
                    //使用自定义任务推送
                    TaskProcess.SendTask(task);//调度NDC或杭奥或国自设备
                    //TaskProcess.SendGZTask(task);///调度国自设备
                });
            }
            else
            {
                LogHelper.Info("暂无任务");
            }
        }
        public static ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
            var gzResult = new ReturnResult();
            //var db = DbHelper.GetDbClient();
            //var db = new SqlHelper<object>().GetInstance();
            //ModbusHelper.Relink();
            //var productionLineInfo = Settings.ProductionLines[0];
core/WMSCore.cs
File was renamed from ServiceCore/WMSCore.cs
@@ -1,4 +1,4 @@
using HH.WCS.Mobox3.AnGang.Helper;

using System;
using System.Collections.Generic;
using System.Linq;
@@ -6,7 +6,7 @@
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.ServiceCore {
namespace HH.WCS.Mobox3.AnGang.core {
    internal class WMSCore 
    {
       
device/ModbusHelper.cs
File was renamed from Devices/ModbusHelper.cs
@@ -6,7 +6,7 @@
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Helpers
namespace HH.WCS.Mobox3.AnGang.device
{
    /// <summary>
    /// modbus tcp 用第三方的包
device/OpcUaHelper.cs
File was renamed from Devices/OpcUaHelper.cs
@@ -3,7 +3,7 @@
using System;
using Opc.Ua.Configuration;
namespace HH.WCS.Mobox3.AnGang.Devices
namespace HH.WCS.Mobox3.AnGang.device
{
    internal class OpcUaHelper
    {
device/PlcHelper.cs
File was renamed from Devices/PlcHelper.cs
@@ -5,7 +5,7 @@
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Devices
namespace HH.WCS.Mobox3.AnGang.device
{
    internal class PlcHelper
    {
device/S7Helper.cs
File was renamed from Devices/S7Helper.cs
@@ -1,4 +1,4 @@
using HH.WCS.Mobox3.AnGang.Controllers;
using HH.WCS.Mobox3.AnGang.api;
using Newtonsoft.Json.Linq;
using S7.Net;
using S7.Net.Types;
@@ -10,7 +10,7 @@
using System.Threading.Tasks;
using System.Web.Services.Description;
namespace HH.WCS.Mobox3.AnGang.Devices
namespace HH.WCS.Mobox3.AnGang.device
{
    /// <summary>
device/SnapDevice.cs
File was renamed from Devices/SnapDevice.cs
@@ -9,7 +9,7 @@
using NetSDKCS;
namespace HH.WCS.Mobox3.AnGang.Devices {
namespace HH.WCS.Mobox3.AnGang.device {
    public class SnapDevice {
        private IntPtr _LoginID = IntPtr.Zero;
        private IntPtr _PlayID = IntPtr.Zero;
@@ -27,7 +27,7 @@
                //NETClient.SetSnapRevCallBack(_SnapRevCallBack, IntPtr.Zero);
            }
            catch (Exception ex) {
                LogHelper.InfoEx(ex);
                LogHelper.Info($"发生了异常:{ex.Message}");
            }
        }
@@ -35,10 +35,10 @@
            NETClient.Cleanup();
        }
        public void LoadInfo(AppStart.Snap snap) {
        public void LoadInfo(Config.Snap snap) {
            LoadInfo(snap.Ip, snap.Port, snap.Name, snap.Pwd);
        }
        public void LoadInfo(string ip, int port, string name, string pwd) {
            if (IntPtr.Zero == _LoginID) {
                ushort uPort = 0;
@@ -151,7 +151,7 @@
                    }
                }
                catch (Exception ex) {
                    LogHelper.InfoEx(ex);
                    LogHelper.Info($"发生了异常:{ex.Message}");
                    return;
                }
                // 替代Demo程序的Frame图片展示
device/SnapManager.cs
File was renamed from Devices/SnapManager.cs
@@ -4,12 +4,10 @@
using System.Text;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.AppStart;
namespace HH.WCS.Mobox3.AnGang.Devices {
namespace HH.WCS.Mobox3.AnGang.device {
    public class SnapManager {
        private static SnapDevice _snapDevice { get; set; }
        public SnapManager(AppStart.Snap snap) {
        public SnapManager(Config.Snap snap) {
            if (_snapDevice == null) {
                _snapDevice = new SnapDevice();
            }
device/TcpClient.cs
File was renamed from Devices/TcpClient.cs
@@ -1,5 +1,5 @@
using HH.WCS.Mobox3.AnGang;
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.device;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -7,7 +7,7 @@
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Devices {
namespace HH.WCS.Mobox3.AnGang.device {
    internal class TcpClient
    {
        /// <summary>
device/TcpServer.cs
File was renamed from Devices/TcpServer.cs
@@ -1,4 +1,4 @@
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.dispatch;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System;
@@ -8,7 +8,7 @@
using System.Net.Sockets;
using System.Text;
namespace HH.WCS.Mobox3.AnGang.Devices
namespace HH.WCS.Mobox3.AnGang.device
{
    public class TcpServer
    {
models/TN_Count_CG_Detail.cs
New file
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.models {
    /// <summary>
    /// 盘点单明细表
    /// </summary>
    [SugarTable("TN_Count_CG_Detail")]
    public class TN_Count_CG_Detail {
        public string S_COUNT_NO { get; set; }
        public string S_ITEM_CODE { get; set; }
        public string S_CNTR_CODE { get; set; }
        public int N_B_STATE { get; set; }
    }
}
models/TN_Count_Diff.cs
New file
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.models {
    /// <summary>
    /// 盘点差异表
    /// </summary>
    [SugarTable("TN_Count_Diff")]
    public class TN_Count_Diff : BaseModel {
        public string S_COUNT_NO { get; set; }
        public string S_CNTR_CODE { get; set; }
        public float F_QTY { get; set; }
        public float F_ACTUAL_QTY { get; set; }
        public string S_ITEM_CODE { get; set; }
    }
}
models/TN_Count_Order.cs
New file
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.models {
    [SugarTable("TN_Count_Order")]
    public class TN_Count_Order : BaseModel {
        public string S_CP_NO { get; set; }
        /// <summary>
        /// 盘点单号
        /// </summary>
        public string S_COUNT_NO { get; set; }
        /// <summary>
        /// 业务状态:0等待执行 1已执行待生成任务 2任务执行中 3任务完成
        /// </summary>
        public int N_B_STATE { get; set; }
    }
}
models/TN_Count_Plan.cs
New file
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;
namespace HH.WCS.Mobox3.AnGang.models {
    [SugarTable("TN_Count_Plan")]
    public class TN_Count_Plan : BaseModel {
        /// <summary>
        /// 盘点计划号
        /// </summary>
        public string S_CP_NO { get; set; }
        /// <summary>
        /// 盘点类型:货物盘点/货位盘点
        /// </summary>
        public string S_TYPE { get; set; }
        /// <summary>
        /// 盘点状态:0 – 未执行 1 – 启动中 2 – 执行中 3 – 完成 4 – 出错
        /// </summary>
        public int N_B_STATE { get; set; } = 0;
        ///// <summary>
        ///// 计划盘点物料数量
        ///// </summary>
        //public int N_PLAN_TOTAL { get; set; }
        // ------
        public string S_LOC_CODE { get; set; } = "";
        public string S_ITEM_CODE { get; set; } = "";
    }
}
process/DeviceProcess.cs
File was renamed from Helpers/DeviceProcess.cs
@@ -1,8 +1,7 @@
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.device;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.dispatch;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
process/TaskProcess.cs
File was renamed from Helpers/TaskHelper.cs
@@ -1,21 +1,14 @@
using HH.WCS.Mobox3.AnGang.ServiceCore;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helper;
using HH.WCS.Mobox3.AnGang.dispatch;
using HH.WCS.Mobox3.AnGang.wms;
using Newtonsoft.Json;
using Opc.Ua;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using Org.BouncyCastle.Crypto;
using HH.WCS.Mobox3.AnGang.Devices;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.models;
using System;
namespace HH.WCS.Mobox3.AnGang.process {
    internal class TaskHelper {
    internal class TaskProcess {
        #region 任务相关
        //--------------------------------------------------任务相关--------------------------------------------------
        /// <summary>
@@ -35,6 +28,7 @@
                LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
                LocationHelper.BindingLoc(mst.S_END_LOC, mst.S_CNTR_CODE.Split(',').ToList());
            }
        }
        /// <summary>
@@ -59,16 +53,13 @@
        }
        /// <summary>
        /// 任务状态更新处理
        /// </summary>
        /// <param name="mst"></param>
        /// <param name="state"></param>
        internal static void OperateStatus(TN_Task mst, int state) {
            if (state == 4)
            {
            if (state == 4) {
                CacheBitUpdate(mst, true);
            }
            if (state == 6)//卸货完成
@@ -87,15 +78,11 @@
        /// <param name="state"></param>
        /// <param name="forkliftNo"></param>
        /// <param name="extData"></param>
        internal static void OperateReq(string no, int state, string forkliftNo, string extData = "")
        {
            if (state == 1101)
            {
        internal static void OperateReq(string no, int state, string forkliftNo, string extData = "") {
            if (state == 1101) {
                //请求取货,
            }
            if (state == 1102)
            {
            if (state == 1102) {
                //请求卸货,
                //根据终点判断,是cb02的入口,判断内存中状态(要状态时间),允许卸货,通知agv改参数
                var dic = new Dictionary<string, string>();
@@ -106,8 +93,7 @@
                NDC.ChangeOrder(dic);
                //改完参数车子就会自己卸货
            }
            if (state == 1103)
            {
            if (state == 1103) {
                //大铁框叉走以后通知,我们要通知输送线
            }
        }
@@ -115,12 +101,11 @@
        private static object locLocker = new object();
       /// <summary>
        /// <summary>
        /// 推送任务
        /// </summary>
        /// <param name="mst"></param>
        internal static bool SendTask(TN_Task mst)
        {
        internal static bool SendTask(TN_Task mst) {
            var result = false;
            var start = "0"; var end = "0";
@@ -131,10 +116,9 @@
                    start = LocationHelper.GetAgvSite(mst.S_START_LOC);
                    end = LocationHelper.GetAgvSite(mst.S_END_LOC);
                    if (mst.S_TYPE == "空托下线堆叠")
                    {
                        end = LocationHelper.GetAgvSite(mst.S_END_LOC,true);
                    }
                    //if (mst.S_TYPE == "空托下线堆叠") {
                    //    end = LocationHelper.GetAgvSite(mst.S_END_LOC, true);
                    //}
                    LogHelper.Info($"NDC推送任务 {mst.S_CODE};" + "start=" + start + "end= " + end);
                    var startLoc = LocationHelper.GetLoc(mst.S_START_LOC);
@@ -147,19 +131,16 @@
                    dic.Add(new param() { name = "Ctype", value = "0" });
                    if (mst.S_TYPE == "余料下线入库" || mst.S_TYPE == "人工拆盘入库")
                    {
                        dic.Add(new param() { name = "DATA", value = "1024" });
                    }
                    else
                    {
                        dic.Add(new param() { name = "DATA", value = "0" });
                    }
                    //if (mst.S_TYPE == "余料下线入库" || mst.S_TYPE == "人工拆盘入库") {
                    //    dic.Add(new param() { name = "DATA", value = "1024" });
                    //}
                    //else {
                    //    dic.Add(new param() { name = "DATA", value = "0" });
                    //}
                    var res = NDCApi.AddOrderNew(1, 1, mst.S_CODE, dic);//添加新命令
                    if (res != null && (res.err_code == 0 || res.err_code == 50009))
                    {
                    if (res != null && (res.err_code == 0 || res.err_code == 50009)) {
                        //推送成功,修改任务优先级
                        mst.N_B_STATE = 1;
                        mst.S_B_STATE = TN_Task.GetStateStr(1);
@@ -167,16 +148,14 @@
                        result = true;
                        LogHelper.Info($"NDC推送任务成功 {mst.S_CODE}start= {mst.S_START_LOC} + end = {mst.S_END_LOC}");
                    }
                    else
                    {
                    else {
                        LogHelper.Info($"NDC推送任务失败 {mst.S_CODE};Res:" + JsonConvert.SerializeObject(res));
                    }
                }
                else if (mst.N_SCHEDULE_TYPE == 5)//通过杭奥调度设备 
                {
                    //调第三方接口
                    var model = new HanAo.TaskInfoModel
                    {
                    var model = new HanAo.TaskInfoModel {
                        requestPk = mst.S_CODE,
                        frmPos = mst.S_START_LOC,
                        toPos = mst.S_END_LOC,
@@ -188,8 +167,7 @@
                        WCSHelper.UpdateStatus(mst);
                        LogHelper.Info($"杭奥推送任务成功 {mst.S_CODE};" + "start=" + model.frmPos + "end= " + model.toPos);
                    }
                    else
                    {
                    else {
                        LogHelper.Info($"杭奥推送任务失败 {mst.S_CODE};" + JsonConvert.SerializeObject(model));
                    }
                }
@@ -204,8 +182,7 @@
                        WCSHelper.UpdateEQNo(mst);
                        LogHelper.Info($"国自推送任务成功 {mst.S_CODE};" + "start=" + mst.S_START_LOC + "end= " + mst.S_END_LOC);
                    }
                    else
                    {
                    else {
                        LogHelper.Info($"国自推送任务失败 {mst.S_CODE};" + JsonConvert.SerializeObject(mst));
                    }
                }
util/HttpHelper.cs
util/LogHelper.cs
File was renamed from Helpers/LogHelper.cs
@@ -35,8 +35,6 @@
            }
        }
        public static void Info(string message, string name = "") {
            //logger.Info(message);
            ILogger logger = null;
@@ -77,15 +75,6 @@
            }
        }
        #region 自定义方法
        public static void InfoEx(Exception ex) {
            Info($"异常:{ex.Message}");
        }
        public static void InfoApi(string taskType, object model) {
            Info($"触发API:{taskType} " + JsonConvert.SerializeObject(model), "API");
        }
        #endregion
    }
    internal class LogFactory
util/Settings.cs
New file
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.IO;
using HH.WCS.Mobox3.AnGang;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
// 根据 JSON 文件 生成对应的 C# 对象;网址:https://json2csharp.com/
namespace HH.WCS.Mobox3.AnGang {
    public class Settings {
        public static string WebApiUrl { get; set; }
        public static string RCSApiUrl { get; set; }
        public static string NDCApiUrl { get; set; }
        public static string SqlServer { get; set; }
        public static string TCPServerIP { get; set; }
        public static int TCPServerPort { get; set; }
        public static List<Config.Area> Areas { get; set; }
        public static List<Config.Snap> Snaps { get; set; }
        public static string CaptureUrl { get; set; }
        /// <summary>
        /// 库区字典(加载后就不变)
        /// </summary>
        public static Dictionary<string, List<string>> AreaMap { get; set; } = new Dictionary<string, List<string>>();
        public static void Init() {
            // 加载配置文件
            LoadJson();
            // 针对 Areas 进行转换:将 Config 的 List 加载到 Dict 中
            LoadAreas();
        }
        private static void LoadJson() {
            LogHelper.Info("加载配置文件信息 开始");
            // JSON 文件路径
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "./config/config.json");
            try {
                // 读取 JSON 文件内容
                string jsonContent = File.ReadAllText(filePath);
                // 反序列化为 Root 对象
                var root = JsonConvert.DeserializeObject<Config.Root>(jsonContent);
                WebApiUrl = root.WebApiUrl;
                RCSApiUrl = root.RCSApiUrl;
                NDCApiUrl = root.NDCApiUrl;
                SqlServer = root.SqlServer;
                TCPServerIP = root.TCPServerIP;
                TCPServerPort = root.TCPServerPort;
                Areas = root.Areas;
                Snaps = root.Snaps;
                CaptureUrl = root.CaptureUrl;
            }
            catch (FileNotFoundException) {
                LogHelper.Info("JSON 文件未找到");
            }
            catch (JsonException ex) {
                LogHelper.Info($"JSON 解析错误: {ex.Message}");
            }
            catch (Exception ex) {
                LogHelper.Info($"发生错误: {ex.Message}");
            }
            LogHelper.Info("加载配置文件信息 完成");
        }
        private static void LoadAreas() {
            foreach (var area in Areas) {
                AreaMap.Add(area.Name, area.Codes);
            }
        }
    }
    public class Config {
        // Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
        public class Area {
            public string Name { get; set; }
            public List<string> Codes { get; set; }
        }
        public class Root {
            public string WebApiUrl { get; set; }
            public string RCSApiUrl { get; set; }
            public string NDCApiUrl { get; set; }
            public string SqlServer { get; set; }
            public string TCPServerIP { get; set; }
            public int TCPServerPort { get; set; }
            public List<Area> Areas { get; set; }
            public List<Snap> Snaps { get; set; }
            public string CaptureUrl { get; set; }
        }
        public class Snap {
            public string Ip { get; set; }
            public int Port { get; set; }
            public string Name { get; set; }
            public string Pwd { get; set; }
        }
    }
    public class TaskName {
        public const string 产品入库 = "产品入库";
        public const string 产品部分出库 = "产品部分出库";
        public const string 产品部分回库 = "产品部分回库";
        public const string 盘点理货出库 = "盘点理货出库";
        public const string 盘点理货回库 = "盘点理货回库";
    }
}
util/SqlHelper.cs
New file
@@ -0,0 +1,70 @@
using HH.WCS.Mobox3.AnGang;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Linq.Expressions;
namespace HH.WCS.Mobox3.AnGang.util {
    //https://www.donet5.com/Home/Doc
    public class SqlHelper<T> where T : class, new() {
        /// <summary>
        /// 如果用Oracle数据需要包Oracle.ManagedDataAccess/21.15.0,环境netframework 4.62,太新了4.8有的服务器安装不上去
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public SqlSugarClient GetInstance(string url = "") {
            //创建数据库对象
            SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() {
                ConnectionString = string.IsNullOrEmpty(url) ? Settings.SqlServer : url,
                //ConnectionString = @"Data Source=192.168.1.198\sql2008;Initial Catalog=OIMobox;User ID=sa;Password=sa@2015",
                DbType = DbType.SqlServer,
                //ConnectionString = @"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=OIMobox)));User Id=system;Password=Am123123;",
                //DbType = DbType.Oracle,
                IsAutoCloseConnection = true,
                InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息
            });
            //监控所有超过1秒的Sql
            db.Aop.OnLogExecuted = (sql, p) => {
                //执行时间超过1秒
                if (db.Ado.SqlExecutionTime.TotalSeconds > 1) {
                    Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject(p.ToDictionary(it => it.ParameterName, it => it.Value)));
                    //代码CS文件名
                    var fileName = db.Ado.SqlStackTrace.FirstFileName;
                    //代码行数
                    var fileLine = db.Ado.SqlStackTrace.FirstLine;
                    //方法名
                    var FirstMethodName = db.Ado.SqlStackTrace.FirstMethodName;
                }
                //相当于EF的 PrintToMiniProfiler
            };
            //每次设置数值时都去除前导后导空格
            db.Aop.DataExecuted = (value, entity) => {
                entity.EntityColumnInfos.ToList().ForEach(a => {
                    var pvalue = entity.GetValue(a.PropertyName);
                    if (pvalue != null && pvalue.GetType() == typeof(String)) {
                        entity.SetValue(a.PropertyName, pvalue.ToString().Trim());
                    }
                });
            };
            //据转换 (ExecuteCommand才会拦截,查询不行)
            //db.Aop.DataExecuting = (value, entity) => {
            //    //var val=entity.EntityColumnInfo
            //    Console.WriteLine(entity.EntityName);
            //};
            return db;
        }
    }
}
wms/ContainerHelper.cs
File was renamed from Helpers/ContainerHelper.cs
@@ -1,4 +1,4 @@
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.models;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System;
@@ -6,10 +6,10 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Dispatch.NDC;
using HH.WCS.Mobox3.AnGang.Helpers;
using static HH.WCS.Mobox3.AnGang.dispatch.NDC;
using HH.WCS.Mobox3.AnGang.util;
namespace HH.WCS.Mobox3.AnGang.Helper {
namespace HH.WCS.Mobox3.AnGang.wms {
    /// <summary>
    /// 容器帮助类
    /// </summary>
@@ -23,7 +23,7 @@
        /// <returns></returns>
        public static string BindingCG(string cnt, List<string> cGs)
        {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var logs = $"容器:{cnt},货品:{JsonConvert.SerializeObject(cGs)}";
            try
            {
@@ -88,7 +88,7 @@
        /// <returns></returns>
        public static string UnBindingCG(string cnt, List<string> cGs)
        {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var logs = $"容器:{cnt},货品:{JsonConvert.SerializeObject(cGs)}";
            try
            {
wms/LocationHelper.cs
File was renamed from Helpers/LocationHelper.cs
@@ -1,4 +1,4 @@
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.models;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using SqlSugar;
@@ -7,11 +7,10 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using HH.WCS.Mobox3.AnGang.Helpers;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.MoboxResponse;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
using HH.WCS.Mobox3.AnGang.util;
namespace HH.WCS.Mobox3.AnGang.Helper {
namespace HH.WCS.Mobox3.AnGang.wms {
    public class LocationHelper
    {
        private static Dictionary<string, TN_Location> Locations = null;
@@ -54,7 +53,7 @@
        /// <returns></returns>
        internal static List<TN_Location> GetAllLocList()
        {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            return db.Queryable<TN_Location>().ToList();
        }
@@ -131,8 +130,29 @@
        internal static TN_Location GetLoc(string code)
        {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            return db.Queryable<TN_Location>().Where(a => a.S_CODE.Trim() == code).First();
        }
        /// <summary>
        /// 入库锁定终点,出库锁定起点
        /// 你创建任务锁定货位的时候,把锁的来源就是任务号也写上去(加锁的方法加个参数,可空的参数),解锁的时候把来源置空。
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="lockState">1:入库锁、2:出库锁、2:其它锁</param>
        /// <param name="lockSource">锁的来源=任务号</param>
        /// <returns></returns>
        public static bool LockLoc(ref TN_Location loc, int lockState, string lockSource = "") {
            //if (loc == null || loc.N_LOCK_STATE != 0) {
            //    return false;
            //}
            loc.N_LOCK_STATE = lockState;
            loc.S_LOCK_STATE = TN_Location.GetLockStateStr(lockState);
            loc.S_LOCK_OP = lockSource;
            loc.T_MODIFY = System.DateTime.Now;
            return true;
        }
        /// <summary>
@@ -146,7 +166,7 @@
        public static bool LockLoc(string loc, int lockState, string lockSource = "")
        {
            var res = false;
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var model = db.Queryable<TN_Location>().Where(a => a.S_CODE == loc).First();
            LogHelper.Info($"锁货位{loc},状态{lockState},信息" + JsonConvert.SerializeObject(model));
            if (model != null && model.N_LOCK_STATE == 0)
@@ -171,7 +191,7 @@
        {
            LogHelper.Info("UnLockLoc:" + loc);
            var res = false;
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var model = db.Queryable<TN_Location>().Where(a => a.S_CODE == loc).First();
            if (model != null)
            {
@@ -197,7 +217,7 @@
        /// <returns></returns>
        public static string UnBindingLoc(string loc, List<string> cntrs)
        {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var logs = $"货位:{loc},容器:{JsonConvert.SerializeObject(cntrs)}";
            try
            {
@@ -270,7 +290,7 @@
        /// <returns></returns>
        public static string BindingLoc(string loc, List<string> cntrs)
        {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var logs = $"货位:{loc},容器:{JsonConvert.SerializeObject(cntrs)}";
            try
            {
@@ -379,7 +399,7 @@
            LogHelper.Info("触发API:货位容器重置" + JsonConvert.SerializeObject(model), "API");
            var result = new SimpleResult();
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            try
            {
wms/SYSHelper.cs
File was renamed from Helpers/SYSHelper.cs
@@ -1,5 +1,5 @@
using HH.WCS.Mobox3.AnGang.config;
using HH.WCS.Mobox3.AnGang.Helpers;
using HH.WCS.Mobox3.AnGang.util;
using SqlSugar;
using System;
@@ -8,15 +8,15 @@
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.AnGang.Helper
namespace HH.WCS.Mobox3.AnGang.wms
{
    internal class SysHelper
    internal class SYSHelper
    {
        private static object locker = new object();
        internal static int GetSerialNumber(string snType, string prefix) {
            int result = 0;
            lock (locker) {
                var db = DbHelper.GetDbClient();
                var db = new SqlHelper<object>().GetInstance();
                var sId = db.Queryable<OI_SYS_MAXID>().Where(a => a.CN_S_TYPE.Trim() == snType && a.CN_S_PRE.Trim() == prefix).First();
                if (sId != null) {
                    sId.CN_N_MAX++;
wms/WCSHelper.cs
File was renamed from Helpers/WCSHelper.cs
@@ -1,4 +1,4 @@
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.models;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using System;
@@ -6,27 +6,26 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HH.WCS.Mobox3.AnGang.Helpers;
using HH.WCS.Mobox3.AnGang.Consts;
using HH.WCS.Mobox3.AnGang.util;
namespace HH.WCS.Mobox3.AnGang.Helper {
namespace HH.WCS.Mobox3.AnGang.wms {
    internal class WCSHelper {
        internal static string GenerateTaskNo() {
            var id = SysHelper.GetSerialNumber("任务号", "TN");
            var id = SYSHelper.GetSerialNumber("任务号", "TN");
            var date = DateTime.Now.ToString("yyMMdd");
            return $"TN{date}{id.ToString().PadLeft(4, '0')}";
        }
        internal static bool UpdateStatus(TN_Task task, string status) 
        {
            var res = false;
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            task.S_B_STATE = status;
            res = db.Updateable(task).UpdateColumns(it => new { it.S_B_STATE }).ExecuteCommand()>0;
            return res;
        }
        internal static bool UpdateStatus(TN_Task task) {
            var res = false;
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
            task.T_MODIFY = DateTime.Now;
            db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_MODIFY }).ExecuteCommand();
@@ -35,16 +34,53 @@
        internal static bool UpdateEQNo(TN_Task task) {
            var res = false;
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            task.T_MODIFY = DateTime.Now;
            db.Updateable(task).UpdateColumns(it => new { it.S_EQ_TASK_CODE, it.T_MODIFY }).ExecuteCommand();
            return res;
        }
        internal static TN_Task GetTask(string no) {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var task = db.Queryable<TN_Task>().Where(a => a.S_CODE == no).First();
            return task;
        }
        public static TN_Task BuildTask(TN_Location startLoc, TN_Location endLoc, string cntId, string type) {
            TN_Task TN_Task = new TN_Task() {
                S_CODE = GenerateTaskNo(),
                S_START_AREA = startLoc.S_AREA_CODE,
                S_END_AREA = endLoc.S_AREA_CODE,
                S_START_LOC = startLoc.S_CODE,
                S_END_LOC = endLoc.S_CODE,
                S_TYPE = type,
                N_PRIORITY = 3,
                N_SCHEDULE_TYPE = 3, // 国自
                N_B_STATE = 0,
                S_CNTR_CODE = cntId,
            };
            return TN_Task;
        }
        public static TN_Task BuildInboundTask(TN_Location startLoc, string endLocCode, string cntId) {
            var type = TaskName.产品入库;
            var endArea = "HJQ";
            TN_Task TN_Task = new TN_Task() {
                S_CODE = GenerateTaskNo(),
                S_START_AREA = startLoc.S_AREA_CODE,
                S_END_AREA = endArea,
                S_START_LOC = startLoc.S_CODE,
                S_END_LOC = endLocCode,
                S_TYPE = type,
                N_PRIORITY = 3,
                N_SCHEDULE_TYPE = 3, // 国自
                N_B_STATE = 0,
                S_CNTR_CODE = cntId,
            };
            return TN_Task;
        }
        /// <summary>
@@ -90,7 +126,7 @@
            };
            var log = JsonConvert.SerializeObject(TN_Task);
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var res = db.Insertable(TN_Task).ExecuteCommand() > 0;
            if (res)
            {
@@ -130,7 +166,7 @@
                    });
                }
                var log = JsonConvert.SerializeObject(tN_Tasks);
                var db = DbHelper.GetDbClient();
                var db = new SqlHelper<object>().GetInstance();
                var res = db.Insertable<TN_Task>(tN_Tasks).ExecuteCommand() > 0;
                if (res)
                {
@@ -148,13 +184,13 @@
        internal static bool CheckActionRecordExist(string no, int code) {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            return db.Queryable<TN_Task_Action>().Count(a => a.S_TASK_CODE == no && a.N_ACTION_CODE == code) > 0;
        }
        internal static void Begin(TN_Task task, string forklift_no) 
        {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            if (task != null) 
            {
                if (task.N_B_STATE == 1) 
@@ -169,7 +205,7 @@
            }
        }
        internal static void End(TN_Task task) {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            if (task != null) {
                task.N_B_STATE = 3;
                task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
@@ -178,7 +214,7 @@
            }
        }
        internal static void Fail(TN_Task task) {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            if (task != null) {
                //判断有没有取货完成,没有就变成失败。有取货完成默认完成了(跟据项目而定,有些项目人工拉走了也没有放到终点)。
                task.N_B_STATE = 4;
@@ -189,7 +225,7 @@
        internal static bool AddActionRecord(string no, int state, string forkliftNo, string extData)
        {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            var action = new TN_Task_Action()
            {
                N_ACTION_CODE = state,
@@ -202,7 +238,7 @@
        }
        internal static List<TN_Task> GetWaitingTaskList() {
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            return db.Queryable<TN_Task>().Where(a => a.N_B_STATE == 0 && (a.S_B_STATE == "等待" || a.S_B_STATE == "待推送")).ToList();
        }
    }
wms/WMSHelper.cs
File was renamed from Helpers/WMSHelper.cs
@@ -1,6 +1,6 @@
using HH.WCS.Mobox3.AnGang.Controllers;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.Models;
using HH.WCS.Mobox3.AnGang.api;
using HH.WCS.Mobox3.AnGang.dispatch;
using HH.WCS.Mobox3.AnGang.models;
using HH.WCS.Mobox3.AnGang.config;
using System;
using System.Collections.Generic;
@@ -10,11 +10,10 @@
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using static HH.WCS.Mobox3.AnGang.Controllers.ApiModel;
using HH.WCS.Mobox3.AnGang.Helpers;
using static HH.WCS.Mobox3.AnGang.Dtos.Response.MoboxResponse;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
using HH.WCS.Mobox3.AnGang.util;
namespace HH.WCS.Mobox3.AnGang.Helper
namespace HH.WCS.Mobox3.AnGang.wms
{
    /// <summary>
    /// wms管到作业
@@ -29,7 +28,7 @@
        internal static SimpleResult PDACancleTask(CancleTaskInfo model)
        {
            SimpleResult simpleResult = new SimpleResult();
            var db = DbHelper.GetDbClient();
            var db = new SqlHelper<object>().GetInstance();
            try
            {
                if (model.taskNO.Length > 0)