chengsc
2025-05-06 d06e44eb1c8818c8d19709602631eb7888d4f0e9
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
using Admin.NET.Core.Service;
using DocumentFormat.OpenXml.Office2010.ExcelAc;
using Furion.InstantMessaging;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace WCS.Application;
 
/// <summary>
/// 任务日志集线器
/// </summary>
[MapHub("/hubs/PlcDevice")]
public class PlcDeviceHub : Hub<IPlcDeviceHub>
{
    private static readonly SysCacheService _sysCacheService = App.GetRequiredService<SysCacheService>();
    private static bool boRunningState = false;
    private static CancellationTokenSource cts;//取消线程标识
    private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
    public PlcDeviceHub()
    {
    }
 
    /// <summary>
    /// 连接
    /// </summary>
    /// <returns></returns>
    public override async Task OnConnectedAsync()
    {
        var httpContext = Context.GetHttpContext();
        var userId = (httpContext.User.FindFirst(ClaimConst.UserId)?.Value).ToLong();
        _sysCacheService.Set("PlcDeviceHub:" + Context.ConnectionId, userId);
        if (!boRunningState)
        {
            //开启读取服务线程
            boRunningState = true;
            cts = new CancellationTokenSource();//取消线程标识
            //StartRead();
        }
        await base.OnConnectedAsync();
    }
 
    /// <summary>
    /// 断开
    /// </summary>
    /// <param name="exception"></param>
    /// <returns></returns>
    public override async Task OnDisconnectedAsync(Exception exception)
    {
        _sysCacheService.Remove("PlcDeviceHub:" + Context.ConnectionId);
        //如果没有连接了 就关闭线程不读了
        if (_sysCacheService.GetKeysByPrefixKey("PlcDeviceHub").Count == 0)
        {
            cts.Cancel();
            boRunningState = false;
        }
        await base.OnDisconnectedAsync(exception);
    }
 
    /// <summary>
    /// 开启读取plc线程
    /// </summary>
    public static void StartRead()
    {
        Task.Run(() =>
        {
            // 用于保存每个设备的初始状态
            var initialStates = new Dictionary<long, WcsDeviceOutput>();
 
            var listPlc = _db.Queryable<WcsPlc>().Where(s => s.Type == PLCTypeEnum.StackingMachine || s.Type == PLCTypeEnum.ConveyorLine).Where(s => s.Enable == YesNoEnum.Y).ToList();
            var listPlcId = listPlc.Select(s => s.Id).ToList();
            var listPlcDevice = _db.Queryable<WcsDevice>().Where(s => s.DeviceType == DeviceTypeEnum.Business && listPlcId.Contains(s.PlcId)).Select<WcsDeviceOutput>().ToList();
            var listPlcDeviceId = listPlcDevice.Select(s => s.Id).ToList();
            var listPlcStation = _db.Queryable<WcsPosition>().Where(s => listPlcDeviceId.Contains(s.DeviceId)).ToList();
            while (true)
            {
                try
                {
                    //获取跺机的状态
                    foreach (var modDevice in listPlcDevice)
                    {
                        //取消线程
                        if (cts.Token.IsCancellationRequested)
                        {
                            throw new OperationCanceledException();
                        }
                        var modPlc = listPlc.Where(s => s.Id == modDevice.PlcId).FirstOrDefault();
                        modDevice.Type = modPlc.Type;
                        //读取plc的值
                        var modConn = PLCTaskAction.listPlcConn.FirstOrDefault(s => s != null && s.PlcId == modDevice.PlcId);
                        if (modConn == null)
                        {
                            modDevice.Status = false;
                            continue;
                        }
                        else
                        {
                            modDevice.Status = modConn.Connected;
                        }
                        if (modConn.Connected)
                        {
                            var listPosition = listPlcStation.Where(s => s.DeviceId == modDevice.Id).ToList();
                            (var result, var plc) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos);
                            modDevice.Plc = Convert.ToString(plc);
                            (result, var wcs) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                            modDevice.Wcs = Convert.ToString(wcs);
                            //任务号
                            var modPositionTask = listPosition.FirstOrDefault(s => s.Text == "任务号");
                            if (modPositionTask != null)
                            {
                                (result, var taskNo) = modConn.GetPlcDBValue(modPositionTask.PosType, modDevice.DbNumber, modPositionTask.PlcPos, modPositionTask.StringLength);
                                modDevice.TaskNo = Convert.ToString(taskNo);
                            }
                            //任务类型
                            var modPositionTaskType = listPosition.FirstOrDefault(s => s.Text == "任务类型");
                            if (modPositionTaskType != null)
                            {
                                (result, var taskType) = modConn.GetPlcDBValue(modPositionTaskType.PosType, modDevice.DbNumber, modPositionTaskType.PlcPos);
                                modDevice.TaskType = (TaskTypeEnum)Convert.ToInt32(taskType);
                            }
                            //起始工位
                            var modPositionStartLocatNo = listPosition.FirstOrDefault(s => s.Text == "起始工位");
                            if (modPositionStartLocatNo != null)
                            {
                                (result, var startLocatNo) = modConn.GetPlcDBValue(modPositionStartLocatNo.PosType, modDevice.DbNumber, modPositionStartLocatNo.PlcPos);
                                modDevice.StartLocatNo = Convert.ToString(startLocatNo);
                            }
                            //目的工位
                            var modPositionEndLocatNo = listPosition.FirstOrDefault(s => s.Text == "目的工位");
                            if (modPositionEndLocatNo != null)
                            {
                                (result, var endLocatNo) = modConn.GetPlcDBValue(modPositionEndLocatNo.PosType, modDevice.DbNumber, modPositionEndLocatNo.PlcPos);
                                modDevice.EndLocatNo = Convert.ToString(endLocatNo);
                            }
                            //托盘码
                            var modPositionPalletNo = listPosition.FirstOrDefault(s => s.Text == "托盘码");
                            if (modPositionPalletNo != null)
                            {
                                (result, var palletNo) = modConn.GetPlcDBValue(modPositionPalletNo.PosType, modDevice.DbNumber, modPositionPalletNo.PlcPos, modPositionPalletNo.StringLength);
                                modDevice.PalletNo = Convert.ToString(palletNo);
                            }
                            if (modPlc.Type == PLCTypeEnum.ConveyorLine)
                            {
                                //放货排
                                var modPositionReleaseRow = listPosition.FirstOrDefault(s => s.Text == "放货排");
                                if (modPositionReleaseRow != null)
                                {
                                    (result, var releaseRow) = modConn.GetPlcDBValue(modPositionReleaseRow.PosType, modDevice.DbNumber, modPositionReleaseRow.PlcPos);
                                    modDevice.ReleaseRow = Convert.ToInt32(releaseRow);
                                }
                                //放货列
                                var modPositionReleaseCol = listPosition.FirstOrDefault(s => s.Text == "放货列");
                                if (modPositionReleaseCol != null)
                                {
                                    (result, var releaseCol) = modConn.GetPlcDBValue(modPositionReleaseCol.PosType, modDevice.DbNumber, modPositionReleaseCol.PlcPos);
                                    modDevice.ReleaseCol = Convert.ToInt32(releaseCol);
                                }
                                //放货层
                                var modPositionReleaseStorey = listPosition.FirstOrDefault(s => s.Text == "放货层");
                                if (modPositionReleaseStorey != null)
                                {
                                    (result, var releaseStorey) = modConn.GetPlcDBValue(modPositionReleaseStorey.PosType, modDevice.DbNumber, modPositionReleaseStorey.PlcPos);
                                    modDevice.ReleaseStorey = Convert.ToInt32(releaseStorey);
                                }
                                //取货排
                                var modPositionPickRow = listPosition.FirstOrDefault(s => s.Text == "取货排");
                                if (modPositionPickRow != null)
                                {
                                    (result, var pickRow) = modConn.GetPlcDBValue(modPositionPickRow.PosType, modDevice.DbNumber, modPositionPickRow.PlcPos);
                                    modDevice.PickRow = Convert.ToInt32(pickRow);
                                }
                                //取货列
                                var modPositionPickCol = listPosition.FirstOrDefault(s => s.Text == "取货列");
                                if (modPositionPickCol != null)
                                {
                                    (result, var pickCol) = modConn.GetPlcDBValue(modPositionPickCol.PosType, modDevice.DbNumber, modPositionPickCol.PlcPos);
                                    modDevice.PickCol = Convert.ToInt32(pickCol);
                                }
                                //取货层
                                var modPositionPickStorey = listPosition.FirstOrDefault(s => s.Text == "取货层");
                                if (modPositionPickStorey != null)
                                {
                                    (result, var pickStorey) = modConn.GetPlcDBValue(modPositionPickStorey.PosType, modDevice.DbNumber, modPositionPickStorey.PlcPos);
                                    modDevice.PickStorey = Convert.ToInt32(pickStorey);
                                }
 
                                if (modPlc.Type == PLCTypeEnum.StackingMachine)
                                {
                                    //跺机的起始工位用取货排列层
                                    modDevice.StartLocatNo = $"{modDevice.PickRow.ToString()}{modDevice.PickCol.ToString()}{modDevice.PickStorey.ToString()}";
                                    //跺机的目的工位用放货排列层
                                    modDevice.EndLocatNo = $"{modDevice.ReleaseRow.ToString()}{modDevice.ReleaseCol.ToString()}{modDevice.ReleaseStorey.ToString()}";
                                }
                            }
                        }
                        //else
                        //{
                        //    //测试
                        //    modDevice.TaskNo = "TK00001";
                        //    modDevice.TaskType = TaskTypeEnum.In;
                        //    modDevice.Wcs = new Random().Next(1000).ToString();
                        //    modDevice.Plc = new Random().Next(1000).ToString();
                        //    modDevice.Status = true;
                        //}
                        // 比较之前的状态
                        if (initialStates.TryGetValue(modDevice.Id, out var initialState))
                        {
                            if (modDevice.Status != initialState.Status ||
                                (modDevice.Plc.IsNullOrEmpty() && modDevice.Plc != initialState.Plc) ||
                                modDevice.Wcs != initialState.Wcs ||
                                modDevice.TaskNo != initialState.TaskNo ||
                                modDevice.TaskType != initialState.TaskType ||
                                modDevice.StartLocatNo != initialState.StartLocatNo ||
                                modDevice.EndLocatNo != initialState.EndLocatNo ||
                                modDevice.PalletNo != initialState.PalletNo ||
                                (modPlc.Type == PLCTypeEnum.ConveyorLine &&
                                    (modDevice.ReleaseRow != initialState.ReleaseRow ||
                                     modDevice.ReleaseCol != initialState.ReleaseCol ||
                                     modDevice.ReleaseStorey != initialState.ReleaseStorey ||
                                     modDevice.PickRow != initialState.PickRow ||
                                     modDevice.PickCol != initialState.PickCol ||
                                     modDevice.PickStorey != initialState.PickStorey)))
                            {
                                // 通知用户变更
                                //HubUtil.PublicPlcDevice(modDevice);
                            }
                        }
                        initialStates[modDevice.Id] = modDevice.Adapt<WcsDeviceOutput>();
                    }
                    Thread.Sleep(2000);
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception)
                {
 
                }
            }
        }, cts.Token);
    }
}