zs
2025-05-18 4b3fd35893972bb05fd7ab89dc624ab805093ff3
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
//using CMS.Extensions.Variable;
//using CMS.Plugin.FlowManagement.Abstractions.FlowBusiness;
//using CMS.Plugin.PipeLineLems.Apis;
//using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.MyTestEntityNames;
//using CMS.Plugin.PipeLineLems.Domain.MyTestEntityNames;
//using CMS.Plugin.PipeLineLems.Jobs;
//using CMS.Plugin.ProcessManagement.Abstractions;
//using CMS.Plugin.TraceManagement.Abstractions.Models.Traces;
//using CMS.Plugin.TraceManagement.Abstractions;
//using CMS.Project;
//using CMS.Project.Abstractions;
//using CMS.Unit.RuntimeValue.Abstractions;
//using KissUtil.Extensions;
//using Microsoft.Extensions.DependencyInjection;
//using Microsoft.Extensions.Logging;
//using System;
//using Volo.Abp.BackgroundJobs;
//using Volo.Abp.Uow;
 
//namespace CMS.Plugin.PipeLineLems.ProjectService
//{
//    /// <summary>
//    /// 工程服务,和工程关联的后台服务,当<see cref="IProjectServiceRunner"/>以当前Key调用时会被执行
//    /// </summary>
//    public class PipeLineLemsProjectService : BaseProjectService
//    {
//        private IServiceProvider _serviceProvider;
//        private readonly ILogger<PipeLineLemsProjectService> _logger;
//        private readonly IVariableDataCache _variableDataCache;
 
//        /// <summary>
//        /// 变量服务
//        /// </summary>
//        private readonly VariableService _variableService;
//        private FlowVariableChannelListener _channelListener;
//        private Dictionary<string, string> _monitorVariableNames;
 
//        /// <summary>
//        /// 服务的Key,唯一,供<see cref="IProjectServiceRunner"/>使用
//        /// </summary>
//        public override string Key => "PipeLineLems";
 
//        /// <summary>
//        /// 服务描述,显示在服务列表UI上的名称
//        /// </summary>
//        public override string Description => "PipeLineLems服务";
 
//        /// <summary>
//        /// 启用授权
//        /// </summary>
//        public override bool AuthRequired => true;
 
//        /// <summary>
//        /// Initializes a new instance of the <see cref="PipeLineLemsProjectService"/> class.
//        /// </summary>
//        /// <param name="logger">The logger.</param>
//        /// <param name="variableDataCache">The variable data cache.</param>
//        public PipeLineLemsProjectService(
//            VariableService variableService,
//            IServiceProvider serviceProvider, ILogger<PipeLineLemsProjectService> logger, IVariableDataCache variableDataCache)
//        {
//            _serviceProvider = serviceProvider;
//            _logger = logger;
//            _variableDataCache = variableDataCache;
//            _variableService = variableService;
//        }
 
//        /// <summary>
//        /// 开启服务
//        /// </summary>
//        /// <param name="serviceProvider">具有工程上下文的实例</param>
//        public override async Task StartAsync(IServiceProvider serviceProvider)
//        {
//            if (State == ProjectServiceState.Started)
//            {
//                return;
//            }
 
//            // 监听变量
//            _monitorVariableNames = new Dictionary<string, string>
//            {
//                { "打码进站信号", "打码进站信号(描述)" },
//                { "切割进站信号", "切割进站信号(描述)" },
//            };
 
//            // 创建通道监听
//            _channelListener?.Token?.Dispose();
//            _channelListener = new FlowVariableChannelListener(_logger, _variableDataCache);
//            _channelListener.CreateChannel(Key, waitListener: false, timeout: TimeSpan.FromSeconds(30), variableFilter: _monitorVariableNames.Keys.ToHashSet());
//            _channelListener.TagChanged += OnTagValueChanged;
 
//            await base.StartAsync(serviceProvider);
//        }
 
//        /// <summary>
//        /// 停止服务
//        /// </summary>
//        /// <param name="serviceProvider">具有工程上下文的实例</param>
//        public override async Task StopAsync(IServiceProvider serviceProvider)
//        {
//            if (_channelListener != null)
//            {
//                // 释放监听
//                _channelListener.TagChanged -= OnTagValueChanged;
//                _channelListener.Token.Dispose();
//                _channelListener = null;
//            }
 
//            // 使用后台作业异步处理
//            //await _serviceProvider.GetRequiredService<IBackgroundJobManager>().EnqueueAsync(new PipeLineLemsArgs
//            //{
//            //    Subject = "PipeLineLems_Subject",
//            //    Body = "PipeLineLems_Body",
//            //});
 
 
//            await base.StopAsync(serviceProvider);
//        }
 
//        /// <summary>
//        /// Called when [tag value changed].
//        /// </summary>
//        /// <param name="sender">The sender.</param>
//        /// <param name="e">The <see cref="TagChangedEventArgs"/> instance containing the event data.</param>
//        private async void OnTagValueChanged(object sender, TagChangedEventArgs e)
//        {
//            var changeds = e.Changeds.Where(x => _monitorVariableNames != null && _monitorVariableNames.ContainsKey(x.Name));
//            if (!changeds.Any())
//            {
//                return;
//            }
 
//            foreach (var changed in changeds)
//            {
//                var oldValue = changed.Old?.Value;
//                var newValue = changed.New?.Value;
//                var traceId = e.TraceId;
 
//                _logger.LogInformation($"{changed.Name} 变量值发生变化,旧值{oldValue}=新值{newValue},TraceId={traceId}");
 
//                if (changed.Name == "打码进站信号" && changed.New?.Value.SafeString().ToBool() == true)
//                {
 
//                    // TODO: 处理变量值变化
//                    // Tips:https://cms-docs.shengyc.com/cms/api/%E5%90%8E%E7%AB%AF#3-%E5%8F%98%E9%87%8F%E6%A8%A1%E5%9D%97
//                    /* 说明:通过订阅 IVariableDataCache.TagChanged 事件,您可以实时监控变量的变化。此事件会传递所有变量至事件处理函数,因此,业务层需在函数中筛选关注的变量。
//                        注意事项:
//                        (1)性能影响: 发布事件时,事件的发送者将阻塞流程。因此,强烈建议避免在事件处理函数中执行 I/ O 操作、HTTP 接口访问或其他耗时操作,以防止对系统性能产生严重影响,导致整个系统响应延迟。
//                        (2)高频率触发: 由于事件订阅了全量变量,触发频率可能非常高。
//                        (3)异步处理: 鉴于事件触发频率很高,建议业务层在筛选关注变量后,使用 Task 启动新线程处理业务逻辑,以避免阻塞核心的变量监听功能,实现业务层与平台基座的解耦。
//                        (4)并发管理: 如果业务层并发量大,必须优化代码设计和实施,以减少在高并发情况下的系统资源消耗,防止系统性能问题。
//                        (5)代码安全: 安装并使用 CMS.CodeAnalysis 分析器来分析 IVariableDataCache.TagChanged 的使用情况。该工具能在使用不当时提供编译错误,帮助您提高代码质量。*/
 
//                    _ = Task.Run(async () =>
//                    {
//                        await HanlderForPringBarCodeAsync();
//                        // 例1:同步处理
//                        //await ProcessAsync();
 
//                        // 例2:调用外部API
//                        //await ExecuteExternalApiAsync();
//                    });
//                }
 
//                if (changed.Name == "切割进站信号" && changed.New?.Value.SafeString().ToBool() == true)
//                {
 
//                    // TODO: 处理变量值变化
//                    // Tips:https://cms-docs.shengyc.com/cms/api/%E5%90%8E%E7%AB%AF#3-%E5%8F%98%E9%87%8F%E6%A8%A1%E5%9D%97
//                    /* 说明:通过订阅 IVariableDataCache.TagChanged 事件,您可以实时监控变量的变化。此事件会传递所有变量至事件处理函数,因此,业务层需在函数中筛选关注的变量。
//                        注意事项:
//                        (1)性能影响: 发布事件时,事件的发送者将阻塞流程。因此,强烈建议避免在事件处理函数中执行 I/ O 操作、HTTP 接口访问或其他耗时操作,以防止对系统性能产生严重影响,导致整个系统响应延迟。
//                        (2)高频率触发: 由于事件订阅了全量变量,触发频率可能非常高。
//                        (3)异步处理: 鉴于事件触发频率很高,建议业务层在筛选关注变量后,使用 Task 启动新线程处理业务逻辑,以避免阻塞核心的变量监听功能,实现业务层与平台基座的解耦。
//                        (4)并发管理: 如果业务层并发量大,必须优化代码设计和实施,以减少在高并发情况下的系统资源消耗,防止系统性能问题。
//                        (5)代码安全: 安装并使用 CMS.CodeAnalysis 分析器来分析 IVariableDataCache.TagChanged 的使用情况。该工具能在使用不当时提供编译错误,帮助您提高代码质量。*/
 
//                    _ = Task.Run(async () =>
//                    {
//                        await HanlderForCutAsync();
//                        // 例1:同步处理
//                        //await ProcessAsync();
 
//                        // 例2:调用外部API
//                        //await ExecuteExternalApiAsync();
//                    });
//                }
//            }
//        }
 
//        /// <summary>
//        /// Processes the asynchronous.
//        /// </summary>
//        private async Task ProcessAsync()
//        {
//            using var scope = _serviceProvider.CreateScope();
//            var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
//            using var uow = unitOfWorkManager.Begin(requiresNew: true);
//            var mytestentitynameRepository = scope.ServiceProvider.GetRequiredService<IMyTestEntityNameRepository>();
//            var count = await mytestentitynameRepository.GetCountAsync();
 
//            // 如果有更新数据库操作,需提交保存
//            // await uow.SaveChangesAsync();
 
//            _logger.LogInformation($"ProcessAsync,Count={count}");
//        }
 
//        /// <summary>
//        /// Executes the external API.
//        /// </summary>
//        private async Task ExecuteExternalApiAsync()
//        {
//            try
//            {
//                await _serviceProvider.GetRequiredService<IPipeLineLemsExternalApi>().CreateAsync(new MyTestEntityNameCreateDto
//                {
//                    Name = "MyTestEntityName_Name",
//                    Code = "MyTestEntityName_Code",
//                });
//            }
//            catch (Exception e)
//            {
//                _logger.LogException(e);
//            }
//        }
 
//        /// <summary>
//        /// 打码
//        /// </summary>
//        /// <returns></returns>
//        private async Task HanlderForPringBarCodeAsync()
//        {
 
//            var plcTaskNo = await _variableService.ReadValueAsync("打码进站PLC任务号");
 
//            if (string.IsNullOrEmpty(plcTaskNo?.Content?.Value.SafeString().ToString()))
//            {
 
//            }
//            else
//            {
//                var myTaskNo = plcTaskNo.Content.Value.SafeString().ToString();
//                //TODO:暂时先写入 内部变量
//                Dictionary<string, object?> keyValuePairs = new Dictionary<string, object?>
//                    {
//                        { "打码工件1", "11111111" },
//                        { "打码工件2", "22222222" },
//                        { "打码工件3", "33333333" }
//                    };
//                _variableService.WriteValueAsync(keyValuePairs);
 
//                //TODO:模拟采集参数
//                keyValuePairs = new Dictionary<string, object?>
//                    {
//                        { "打码速度", 100},
//                        { "打码质量", 2},
//                    };
//                var ret2 = _variableService.WriteValueAsync(keyValuePairs);
 
//                //TODO:暂时生成产品ID
//                //var productID = Guid.NewGuid().ToString();
//                var productID = DateTime.Now.ToString("yyyyMMddHHmmssfff");
//                keyValuePairs = new Dictionary<string, object?>
//                    {
//                        { "打码_ProductID", productID},
//                    };
//                var ret = _variableService.WriteValueAsync(keyValuePairs);
//            }
//        }
 
 
//        /// <summary>
//        /// 切割
//        /// </summary>
//        /// <returns></returns>
//        private async Task HanlderForCutAsync()
//        {
 
//            var plcTaskNo = await _variableService.ReadValueAsync("切割进站PLC任务号");
 
//            if (string.IsNullOrEmpty(plcTaskNo?.Content?.Value.SafeString().ToString()))
//            {
 
//            }
//            else
//            {
//                var myTaskNo = plcTaskNo.Content.Value.SafeString().ToString();
//                //TODO:暂时先写入 内部变量
//                Dictionary<string, object?> keyValuePairs = new Dictionary<string, object?>
//                    {
//                        { "切割1", "555555" },
//                        { "切割2", "66666" },
//                        { "切割3", "77777" }
//                    };
//                _variableService.WriteValueAsync(keyValuePairs);
 
//                //TODO:模拟采集参数
//                keyValuePairs = new Dictionary<string, object?>
//                    {
//                        { "切割速度", 99},
//                        { "切割质量", 1},
//                    };
//                var ret2 = _variableService.WriteValueAsync(keyValuePairs);
 
//                //TODO:暂时生成产品ID
//                //获取上一个工序的产品ID
//                //根据工序名获取工序对象
//                var _workSectionManager = _serviceProvider.GetRequiredService<IWorkSectionManager>();
//                var lastWorkSection = "打码工序";
//                var workSection = await _workSectionManager.GetByNameAsync(lastWorkSection);
 
//                //获取工单数据(从末工序查询3个产品)
//                //读取scms_productions表,根据当前时间查询最近3条记录
//                var traceManager = _serviceProvider.GetRequiredService<ITraceProvider>();
//                GetTracesRequest request = new GetTracesRequest()
//                {
//                    WorkSectionId = workSection.Id,
//                };
//                TraceModel traceModel = null;
//                var list = await traceManager.GetTracesAsync(request);
//                if (list?.Count > 0)
//                {
//                    //重新排序
//                    list = list.OrderByDescending(x => x.FinishTime).ToList();
//                    traceModel = list.First();
//                }
//                //var productID = Guid.NewGuid().ToString();
//                var productID = DateTime.Now.ToString("yyyyMMddHHmmssfff");
//                if (traceModel != null)
//                {
//                    productID = traceModel.SerialNumber;
//                }
//                keyValuePairs = new Dictionary<string, object?>
//                    {
//                        { "切割_ProductID", productID},
//                    };
//                var ret = _variableService.WriteValueAsync(keyValuePairs);
//            }
//        }
//    }
//}