kazelee
2025-05-09 62e3ff7506396fcb7f7737900806e838c2466aa3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
using System;
using System.Collections.Generic;
using System.Linq;
 
using HH.WCS.Mobox3.DSZSH.Dispatch;
using HH.WCS.Mobox3.DSZSH.Helpers;
using HH.WCS.Mobox3.DSZSH.Models;
using HH.WCS.Mobox3.DSZSH.Helper;
 
using Newtonsoft.Json;
 
using SqlSugar;
 
using static HH.WCS.Mobox3.DSZSH.Dtos.Response.MoboxResponse;
using static HH.WCS.Mobox3.DSZSH.Helpers.ResultHelper;
 
namespace HH.WCS.Mobox3.DSZSH.Helpers.Model {
    /// <summary>
    /// 任务帮助类
    /// </summary>
    public class TaskHelper {
        /// <summary>
        /// 生成任务号
        /// </summary>
        /// <returns></returns>
        private static string GenerateTaskNo() {
            var id = SysHelper.GetSerialNumber("任务号", "TN");
            var date = DateTime.Now.ToString("yyMMdd");
            return $"TN{date}{id.ToString().PadLeft(4, '0')}";
        }
 
        /// <summary>
        /// 创建搬运任务,返回任务是否创建成功
        /// </summary>
        /// <remarks>
        /// 不会检查参数合法性,使用前请确保货位号和容器号存在
        /// </remarks>
        /// <param name="from">起点货位号</param>
        /// <param name="cnt">容器号</param>
        /// <param name="to">终点货位号</param>
        /// <param name="type">任务类型/名称</param>
        /// <param name="pri">优先级</param>
        /// <returns></returns>
        public static bool CreateTask(string from, string cnt, string to, string type, int pri = 3) {
            var startLoc = LocationHelper.GetLocation(from);
            var endLoc = LocationHelper.GetLocation(to);
 
            TN_Task TN_Task = new TN_Task() {
                S_CODE = GenerateTaskNo(),
                S_START_AREA = startLoc?.S_AREA_CODE ?? "", // 如果为null返回空字符串
                S_END_AREA = endLoc?.S_AREA_CODE ?? "", // 如果为null返回空字符串
                S_START_LOC = from,
                S_END_LOC = to,
                S_TYPE = type,
                N_PRIORITY = pri,
                N_SCHEDULE_TYPE = 1,
                N_B_STATE = 0,
                S_CNTR_CODE = cnt,
            };
 
            var db = DbHelper.GetDbClient();
            var log = JsonConvert.SerializeObject(TN_Task);
            try {
                // 内部不使用事务(只涉及单个插入操作),由外部声明事务
                var res = db.Insertable(TN_Task).ExecuteCommand() > 0;
                if (res) {
                    LogHelper.Info($"插入任务成功:{log}");
                }
                else {
                    LogHelper.Info($"插入任务失败:{log}");
                }
                return res;
            }
            catch (Exception ex) {
                LogHelper.InfoEx(ex);
                return false;
            }
        }
 
        /// <summary>
        /// 创建任务,并将 是否创建成功 的信息通过 <see cref="LogHelper.Info(string, string)"/> 打印日志
        /// </summary>
        /// <param name="from">起点货位号</param>
        /// <param name="cnt">容器号</param>
        /// <param name="to">终点货位号</param>
        /// <param name="type">任务类型/名称</param>
        /// <param name="pri">优先级</param>
        /// <returns>创建任务是否成功</returns>
        public static bool LogCreateTask(string from, string cnt, string to, string type, int pri = 3) {
            var db = DbHelper.GetDbClient();
            using (var tran = db.Ado.UseTran()) {
                if (TaskHelper.CreateTask(from, cnt, to, type, pri)) {
                    LocationHelper.LockLoc(from, 2); // 起点出库锁,
                    LocationHelper.LockLoc(to, 1); // 终点入库锁
                    tran.CommitTran();
                    LogHelper.Info($"生成 '{type}' 成功,容器号 '{cnt}',起点 '{from}',终点 '{to}'");
                    return true;
                }
                else {
                    tran.RollbackTran();
                    LogHelper.Info($"生成 '{type}' 失败,容器号 '{cnt}',起点 '{from}',终点 '{to}'");
                    return false;
                }
            }
        }
 
        /// <summary>
        /// 创建任务,使用 <see cref="SimpleResult"/> 返回结果
        /// </summary>
        /// <param name="from">起点货位号</param>
        /// <param name="cnt">容器号</param>
        /// <param name="to">终点货位号</param>
        /// <param name="type">任务类型/名称</param>
        /// <param name="pri">优先级(默认为 3)</param>
        /// <param name="failCode">创建失败时返回的 result code</param>
        /// <returns></returns>
        public static SimpleResult SimpleCreateTask(string from, string cnt, string to, string type, int pri = 3, int failCode = 5) {
            var db = DbHelper.GetDbClient();
            using (var tran = db.Ado.UseTran()) {
                if (TaskHelper.CreateTask(from, cnt, to, type, pri)) {
                    LocationHelper.LockLoc(from, 2); // 起点出库锁,
                    LocationHelper.LockLoc(to, 1); // 终点入库锁
                    return BuildSimpleResult(0, $"生成 '{type}' 成功,容器号 '{cnt}',起点 '{from}',终点 '{to}'");
                }
                else {
                    return BuildSimpleResult(failCode, $"生成 '{type}' 失败,容器号 '{cnt}',起点 '{from}',终点 '{to}'");
                } 
            }
        }
 
        //public static SimpleResult SimpleService(string taskName) {
        //    var db = DbHelper.GetDbClient();
 
        //    try {
                
                
        //    }
        //    catch (Exception) {
 
        //        throw;
        //    }
        //}
 
        /// <summary>
        /// 取货卸货完成,缓存位状态更新
        /// </summary>
        /// <param name="mst"></param>
        /// <param name="load"></param>
        internal static void CacheBitUpdate(TN_Task mst, bool load) {
            var trayCarryCount = mst.N_CNTR_COUNT > 0 ? mst.N_CNTR_COUNT : 1;
            if (load) {
                Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
                LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
                LocationHelper.UnBindingLoc(mst.S_START_LOC, mst.S_CNTR_CODE.Split(',').ToList());
            }
            else {
                Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
                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>
        /// 任务取消,缓存位状态更新
        /// </summary>
        /// <param name="mst"></param>
        internal static void CacheBitCancelUpdate(TN_Task mst) {
            //任务取消,取货完成前的,起点的loadingCount和终点unLoadingCount都清除,取货完成的只处理终点
            if (CheckActionRecordExist(mst.S_CODE, 4)) {
                //根据客户现场要求,如果取货完成任务失败人工拉到终点,我们就当卸货完成处理;如果是人工拉走到其它区域,我们就解锁终点,删除托盘。
                //终点绑定
                CacheBitUpdate(mst, false);
                LocationHelper.UnLockLoc(mst.S_END_LOC);
            }
            else {
 
                //起点终点解锁
                LocationHelper.UnLockLoc(mst.S_START_LOC);
                LocationHelper.UnLockLoc(mst.S_END_LOC);
 
            }
 
        }
 
        
 
        /// <summary>
        /// 任务状态更新处理
        /// </summary>
        /// <param name="mst"></param>
        /// <param name="state"></param>
        internal static void OperateStatus(TN_Task mst, int state) {
            if (state == 4) 
            {
                CacheBitUpdate(mst, true);
            }
            if (state == 6)//卸货完成
            {
                CacheBitUpdate(mst, false);
            }
            if (state == 7) {
                CacheBitCancelUpdate(mst);
            }
        }
 
        /// <summary>
        /// 安全请求
        /// </summary>
        /// <param name="no"></param>
        /// <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)
            {
                //请求取货,
 
            }
            if (state == 1102)
            {
                //请求卸货,
                //根据终点判断,是cb02的入口,判断内存中状态(要状态时间),允许卸货,通知agv改参数
                var dic = new Dictionary<string, string>();
                //< Req >< Order No = 'TN2302020002' ParamNo = '18' Param1 = '12' /></ Req >
                dic.Add("No", no);
                dic.Add("ParamNo", "8");
                dic.Add("Param1", "1");
                NDC.ChangeOrder(dic);
                //改完参数车子就会自己卸货
            }
            if (state == 1103)
            {
                //大铁框叉走以后通知,我们要通知输送线
            }
        }
 
        private static object locLocker = new object();
 
 
        /// <summary>
        /// 推送任务
        /// </summary>
        /// <param name="mst"></param>
        internal static bool SendTask(TN_Task mst) 
        {
            var result = false;
            var start = "0"; var end = "0";
            var taskType = mst.S_TYPE.Trim();
            if (mst.N_B_STATE == 0) {
                if (mst.N_SCHEDULE_TYPE == 1)//通过NDC,hosttoagv调度设备
                {
                    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);
                    }
 
                    LogHelper.Info($"NDC推送任务 {mst.S_CODE};" + "start=" + start + "end= " + end);
                    var startLoc = LocationHelper.GetLoc(mst.S_START_LOC);
                    var endLoc = LocationHelper.GetLoc(mst.S_END_LOC);
                    var dic = new List<param>();
                    dic.Add(new param() { name = "IKey", value = "IKey" });
                    dic.Add(new param() { name = "From", value = start.ToString() });
                    dic.Add(new param() { name = "To", value = end.ToString() });
                    dic.Add(new param() { name = "FUNC", value = startLoc.N_LAYER.ToString() });
 
                    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" });
                    }
 
                    var res = NDCApi.AddOrderNew(1, 1, mst.S_CODE, dic);//添加新命令
                    if (res != null && (res.err_code == 0 || res.err_code == 50009))
                    {
                        //推送成功,修改任务优先级
                        mst.N_B_STATE = 1;
                        mst.S_B_STATE = TN_Task.GetStateStr(1);
                        UpdateStatus(mst);//更新任务状态
                        result = true;
                        LogHelper.Info($"NDC推送任务成功 {mst.S_CODE}start= {mst.S_START_LOC} + end = {mst.S_END_LOC}");
                    }
                    else
                    {
                        LogHelper.Info($"NDC推送任务失败 {mst.S_CODE};Res:" + JsonConvert.SerializeObject(res));
                    }
                }
                else if (mst.N_SCHEDULE_TYPE == 5)//通过杭奥调度设备 
                {
                    //调第三方接口
                    var model = new HanAo.TaskInfoModel
                    {
                        requestPk = mst.S_CODE,
                        frmPos = mst.S_START_LOC,
                        toPos = mst.S_END_LOC,
                        trkType = mst.S_OP_NAME == "入库" ? "1" : "2",
                        contNo = mst.S_CNTR_CODE
                    };
                    if (HanAo.CreateOrder(model)) {
                        mst.N_B_STATE = 1;
                        UpdateStatus(mst);
                        LogHelper.Info($"杭奥推送任务成功 {mst.S_CODE};" + "start=" + model.frmPos + "end= " + model.toPos);
                    }
                    else
                    {
                        LogHelper.Info($"杭奥推送任务失败 {mst.S_CODE};" + JsonConvert.SerializeObject(model));
                    }
                }
                else if (mst.N_SCHEDULE_TYPE == 3) //通过国自调度设备
                {
                    var code = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, JsonConvert.SerializeObject(new { src = mst.S_START_LOC, dst = mst.S_END_LOC }), "p2p");
                    if (code > 0) {
                        //更新任务状态
                        mst.N_B_STATE = 1;
                        mst.S_EQ_TASK_CODE = code.ToString();
                        UpdateStatus(mst);
                        UpdateEQNo(mst);
                        LogHelper.Info($"国自推送任务成功 {mst.S_CODE};" + "start=" + mst.S_START_LOC + "end= " + mst.S_END_LOC);
                    }
                    else
                    {
                        LogHelper.Info($"国自推送任务失败 {mst.S_CODE};" + JsonConvert.SerializeObject(mst));
                    }
                }
 
            }
            return result;
        }
 
 
        internal static bool UpdateStatus(TN_Task task, string status) {
            var res = false;
            var db = DbHelper.GetDbClient();
            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();
            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();
            return res;
        }
 
        internal static bool UpdateEQNo(TN_Task task) {
            var res = false;
            var db = DbHelper.GetDbClient();
            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 task = db.Queryable<TN_Task>().Where(a => a.S_CODE == no).First();
            return task;
        }
 
        public static bool CreateTask(List<CreateTasks> modes) {
            if (modes != null && modes.Count > 0) {
                List<TN_Task> tN_Tasks = new List<TN_Task>();
 
                foreach (var item in modes) {
 
                    var fromLoc = LocationHelper.GetLocation(item.from);
                    var endLoc = LocationHelper.GetLocation(item.to);
 
                    tN_Tasks.Add(new TN_Task() {
                        S_CODE = GenerateTaskNo(),
                        S_START_AREA = fromLoc.S_AREA_CODE,
                        S_END_AREA = endLoc.S_AREA_CODE,
                        S_START_LOC = item.from,
                        S_END_LOC = item.to,
                        S_TYPE = item.taskType,
                        N_PRIORITY = item.pri,
                        N_SCHEDULE_TYPE = 1,
                        N_B_STATE = 0,
                        S_CNTR_CODE = item.cntrInfo,
                    });
                }
                var log = JsonConvert.SerializeObject(tN_Tasks);
                var db = DbHelper.GetDbClient();
                var res = db.Insertable<TN_Task>(tN_Tasks).ExecuteCommand() > 0;
                if (res) {
                    LogHelper.Info($"插入任务成功,{log}");
                }
                else {
                    LogHelper.Info($"插入任务失败,{log}");
                }
                return res;
            }
 
            return false;
        }
 
 
        internal static bool CheckActionRecordExist(string no, int code) {
            var db = DbHelper.GetDbClient();
            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();
            if (task != null) {
                if (task.N_B_STATE == 1) {
                    task.N_B_STATE = 2;
                    task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
                    task.T_START_TIME = System.DateTime.Now;
                    task.S_EQ_NO = forklift_no;
                    db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_START_TIME, it.S_EQ_NO }).ExecuteCommand();
                }
 
            }
        }
 
        internal static void End(TN_Task task) {
            var db = DbHelper.GetDbClient();
            if (task != null) {
                task.N_B_STATE = 3;
                task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
                task.T_END_TIME = DateTime.Now;
                db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.T_END_TIME }).ExecuteCommand();
            }
        }
 
        internal static void Fail(TN_Task task) {
            var db = DbHelper.GetDbClient();
            if (task != null) {
                //判断有没有取货完成,没有就变成失败。有取货完成默认完成了(跟据项目而定,有些项目人工拉走了也没有放到终点)。
                task.N_B_STATE = 4;
                task.S_B_STATE = TN_Task.GetStateStr(task.N_B_STATE);
                db.Updateable(task).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE }).ExecuteCommand();
            }
        }
 
        internal static bool AddActionRecord(string no, int state, string forkliftNo, string extData) {
            var db = DbHelper.GetDbClient();
            var action = new TN_Task_Action() {
                N_ACTION_CODE = state,
                S_TASK_CODE = no,
                S_EQ_CODE = forkliftNo,
                S_EQ_TYPE = "agv",
                S_DATA = extData
            };
            return db.Insertable(action).ExecuteCommand() > 0;
        }
 
        internal static List<TN_Task> GetWaitingTaskList() {
            var db = DbHelper.GetDbClient();
            return db.Queryable<TN_Task>().Where(a => a.N_B_STATE == 0 && (a.S_B_STATE == "等待" || a.S_B_STATE == "待推送")).ToList();
        }
    }
 
    public class CreateTasks {
        public string from { set; get; }
        public string to { set; get; }
        public string taskType { set; get; }
        public int pri { set; get; }
        public string cntrInfo { set; get; }
    }
}