GetSample.cs 27.2 KB
Newer Older
潘栩锋's avatar
潘栩锋 committed
1 2 3 4 5 6 7 8 9 10 11 12 13
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.ComponentModel;
using System.Xml.Serialization;

using Misc;
using FObjBase;
using FlyADBase;
using FLY.Thick.Base.IService;
14
using PropertyChanged;
15 16
using Newtonsoft.Json;
using static Misc.ReverserInfo;
17
using FLY.Thick.Base.Common;
18
using AutoMapper;
19 20
using System.Reflection;
using FLY.OBJComponents.Common;
潘栩锋's avatar
潘栩锋 committed
21 22 23

namespace FLY.Thick.Base.Server
{
潘栩锋's avatar
潘栩锋 committed
24
    public class GSample : IGetSampleService
潘栩锋's avatar
潘栩锋 committed
25
    {
26 27 28 29
        /// <summary>
        /// 报警测试
        /// </summary>

潘栩锋's avatar
潘栩锋 committed
30
        #region IGetSampleService 接口
31

潘栩锋's avatar
潘栩锋 committed
32 33 34
        /// <summary>
        /// 参数:使能
        /// </summary>
35
        public bool Enable { get; set; } = true;
潘栩锋's avatar
潘栩锋 committed
36 37 38 39

        /// <summary>
        /// 参数:速度
        /// </summary>
40 41 42
        public UInt32 Velocity { get; set; } = 500;


潘栩锋's avatar
潘栩锋 committed
43
        /// <summary>
44 45
        /// 参数:样品点范围 单位:脉冲
        /// 样品点直径为 Range*2
潘栩锋's avatar
潘栩锋 committed
46
        /// </summary>
47
        public int SampleRange { get; set; } = 100;
48

潘栩锋's avatar
潘栩锋 committed
49 50

        /// <summary>
51
        /// 滤波窗口,单位 min
潘栩锋's avatar
潘栩锋 committed
52
        /// </summary>
53
        public int Window { get; set; }
54

55 56 57 58
        /// <summary>
        /// 使用%方式检查异常
        /// </summary>
        public bool IsCheckByPercent { get; set; } = true;
59

60
        /// <summary>
61
        /// 异常比例 单位不是%
62
        /// </summary>
63 64
        public double ErrPercent { get; set; } = 0.02;
        
65 66 67 68
        /// <summary>
        /// 异常值
        /// </summary>
        public int ErrValue { get; set; } = 200;
潘栩锋's avatar
潘栩锋 committed
69

70 71 72 73 74
        /// <summary>
        /// 当前 样品X_AD/样品0_AD 与 上一次比较 差异比例 单位不是%
        /// </summary>
        public double CrossErrPercent { get; set; } = 0.02;

75 76 77
        /// <summary>
        /// 样品
        /// </summary>
78
        public SampleCell[] Samples { get; set; }
潘栩锋's avatar
潘栩锋 committed
79 80

        /// <summary>
81 82
        /// 参数:特征查找范围 单位:脉冲
        /// 取样范围 会扩大为 -SearchRange ~ +SearchRange
潘栩锋's avatar
潘栩锋 committed
83
        /// </summary>
84
        public int SearchRange { get; set; } = 100;
85

潘栩锋's avatar
潘栩锋 committed
86
        /// <summary>
87
        /// 特征  相识度 0 正, 1 反
潘栩锋's avatar
潘栩锋 committed
88
        /// </summary>
89
        public SampleFeature[] Features { get; set; } 
90

潘栩锋's avatar
潘栩锋 committed
91

92
        #endregion
93 94
        
        
潘栩锋's avatar
潘栩锋 committed
95 96
        TempFilter2[] tempFilters;
        DIRECTION[] directions;
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
        /// <summary>
        /// 采集状态
        /// </summary>
        public SampleState[] states;
        public enum SampleState
        {
            /// <summary>
            /// 准备采集
            /// </summary>
            ReadyToCapture,
            /// <summary>
            /// 采集成功
            /// </summary>
            Ok,
            /// <summary>
            /// 采集失败
            /// </summary>
            IsFailure
        }
潘栩锋's avatar
潘栩锋 committed
116
        IGageInfoService mGageInfo;
117
        OBJComponents.Server.WarningSystem2 warningSystem;
118
        IFlyADClientAdv flyad;
119
        SampleData last_sampleData;
潘栩锋's avatar
潘栩锋 committed
120 121 122

        public event SampleChangedEventHandler SampleChangedEvent;
        private string param_path;
潘栩锋's avatar
潘栩锋 committed
123 124 125

        
        public GSample():this("gsample.json")
潘栩锋's avatar
潘栩锋 committed
126 127 128
        {

        }
潘栩锋's avatar
潘栩锋 committed
129
        public GSample(string param_path)
潘栩锋's avatar
潘栩锋 committed
130 131 132
        {
            this.param_path = param_path;

潘栩锋's avatar
潘栩锋 committed
133
            Samples = new SampleCell[3];
134

潘栩锋's avatar
潘栩锋 committed
135 136 137
            Features = new SampleFeature[2];
            tempFilters = new TempFilter2[Samples.Count()];
            directions = new DIRECTION[Samples.Count()];
138
            states = new SampleState[Samples.Count()];
潘栩锋's avatar
潘栩锋 committed
139 140 141
            for (int i = 0; i < Samples.Count(); i++)
                tempFilters[i] = new TempFilter2();
            
潘栩锋's avatar
潘栩锋 committed
142
            Enable = true;
143
            SampleRange = 100;//样品范围
潘栩锋's avatar
潘栩锋 committed
144 145
            Velocity = 200;//取样速度
            Window = 3;//移动窗口
146 147 148 149
            IsCheckByPercent = true;
            ErrPercent = 2;
            ErrValue = 200;

潘栩锋's avatar
潘栩锋 committed
150
            Samples[0] = new SampleCell()
151
            {
潘栩锋's avatar
潘栩锋 committed
152
                Enable = true,
153 154
                Position = 200,
                OrgAD = 50300
潘栩锋's avatar
潘栩锋 committed
155
            };
潘栩锋's avatar
潘栩锋 committed
156 157
            directions[0] = DIRECTION.BACKWARD;

潘栩锋's avatar
潘栩锋 committed
158
            Samples[1] = new SampleCell()
159
            {
潘栩锋's avatar
潘栩锋 committed
160
                Enable = false,
161 162
                Position = 0,
                OrgAD = 0
潘栩锋's avatar
潘栩锋 committed
163
            };
潘栩锋's avatar
潘栩锋 committed
164 165
            directions[1] = DIRECTION.FORWARD;

潘栩锋's avatar
潘栩锋 committed
166 167 168 169
            Samples[2] = new SampleCell()
            {
                Enable = false,
                Position = 0,
潘栩锋's avatar
潘栩锋 committed
170
                OrgAD = 0
潘栩锋's avatar
潘栩锋 committed
171
            };
潘栩锋's avatar
潘栩锋 committed
172
            directions[2] = DIRECTION.FORWARD;
173

174
            SearchRange = 100;
潘栩锋's avatar
潘栩锋 committed
175 176 177
            Features[0] = new SampleFeature() { StartPos = 0, EndPos = 0 };
            Features[1] = new SampleFeature() { StartPos = 2000, EndPos = 2100 };

178 179
            if (!Load())
                Save();
潘栩锋's avatar
潘栩锋 committed
180
        }
潘栩锋's avatar
潘栩锋 committed
181
        public virtual void Init(
182
            IFlyADClientAdv flyad,
183
            IGageInfoService gageInfo,
184
            OBJComponents.Server.WarningSystem2 warningSystem) 
185
        {
潘栩锋's avatar
潘栩锋 committed
186
            this.flyad = flyad;
187
            this.mGageInfo = gageInfo;
188
            this.warningSystem = warningSystem;
潘栩锋's avatar
潘栩锋 committed
189 190 191



潘栩锋's avatar
潘栩锋 committed
192 193 194 195
        }

        public bool Load() 
        {
196
            return GSampleJsonDb.Load(this, param_path);
潘栩锋's avatar
潘栩锋 committed
197 198
        }

潘栩锋's avatar
潘栩锋 committed
199 200 201
        /// <summary>
        /// 保存
        /// </summary>
202
        public bool Save() 
潘栩锋's avatar
潘栩锋 committed
203
        {
204
            return GSampleJsonDb.Save(this, param_path);
潘栩锋's avatar
潘栩锋 committed
205 206 207 208 209 210 211 212
        }
        /// <summary>
        /// 1.判断样品取样方向
        /// 2.复位间隔计数
        /// 3.复位所有样品取样状态
        /// </summary>
        /// <param name="scanbegin"></param>
        /// <param name="scanend"></param>
潘栩锋's avatar
潘栩锋 committed
213
        public virtual void Reset(int scanbegin, int scanend)
潘栩锋's avatar
潘栩锋 committed
214
        {
215
            last_sampleData = null;
潘栩锋's avatar
潘栩锋 committed
216
            for (int i = 0; i < Samples.Count(); i++) {
217 218
                SampleCell sample = Samples[i];

潘栩锋's avatar
潘栩锋 committed
219
                int pos = sample.Position;
潘栩锋's avatar
潘栩锋 committed
220 221
                directions[i] = (Math.Abs(pos - scanbegin) < Math.Abs(pos - scanend)) ? Misc.DIRECTION.BACKWARD : Misc.DIRECTION.FORWARD;
                
潘栩锋's avatar
潘栩锋 committed
222
                sample.AD = -1;
223
                states[i] = SampleState.ReadyToCapture;
潘栩锋's avatar
潘栩锋 committed
224
                tempFilters[i].Reset();
潘栩锋's avatar
潘栩锋 committed
225 226
            }
        }
潘栩锋's avatar
潘栩锋 committed
227
        /// <summary>
228
        /// 进入采集周期,设置全部采样点 为准备采集状态
潘栩锋's avatar
潘栩锋 committed
229
        /// </summary>
230
        public void ReadyToCapture()
潘栩锋's avatar
潘栩锋 committed
231
        {
潘栩锋's avatar
潘栩锋 committed
232
            for (int i = 0; i < Samples.Count(); i++)
潘栩锋's avatar
潘栩锋 committed
233
            {
234
                states[i] = SampleState.ReadyToCapture;
潘栩锋's avatar
潘栩锋 committed
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
            }
        }
        /// <summary>
        /// 获取样品测量范围
        /// </summary>
        /// <param name="direction"></param>
        /// <returns>当没有样品,也没有特征,返回null</returns>      
        public Range GetSampleRange(Misc.DIRECTION direction) 
        {
            int b, e;
            if (GetSampleRange(direction, out b, out e))
            {
                return new Range() { Begin = b, End = e };
            }
            else
            {
251
                return new Range();
潘栩锋's avatar
潘栩锋 committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
            }
        }
        /// <summary>
        /// 获取样品测量范围
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns>当没有样品,也没有特征,返回False</returns>
        public virtual bool GetSampleRange(Misc.DIRECTION direction, out int start,out int end)
        {
            start = 0;
            end = 0;
            bool valid = false;
            int b=0, e=0;
潘栩锋's avatar
潘栩锋 committed
267
            int r_idx = (direction == Misc.DIRECTION.FORWARD) ? 0 : 1;
潘栩锋's avatar
潘栩锋 committed
268 269 270 271 272 273 274 275

            if (Features[r_idx].Enable)
            {
                b = Features[r_idx].StartPos;
                e = Features[r_idx].EndPos;
                valid = true;
            }

潘栩锋's avatar
潘栩锋 committed
276
            for(int i=0;i< Samples.Count(); i++)
潘栩锋's avatar
潘栩锋 committed
277
            {
278
                SampleCell sample = Samples[i];
潘栩锋's avatar
潘栩锋 committed
279
                if ((sample.Enable) && (directions[i] == direction))
潘栩锋's avatar
潘栩锋 committed
280
                {
281 282
                    int _b = sample.Position - SampleRange;
                    int _e = sample.Position + SampleRange;
潘栩锋's avatar
潘栩锋 committed
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

                    if (!valid)
                    {
                        b = _b;
                        e = _e;
                        valid = true;
                    }
                    else
                    {
                        if (b > _b)
                            b = _b;

                        if (e < _e)
                            e = _e;
                    }
                }
            }




            if (valid)
            {
                if (Features[r_idx].Enable)
                {
308 309
                    b -= SearchRange;
                    e += SearchRange;
潘栩锋's avatar
潘栩锋 committed
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
                }
                start = b;
                end = e;
            }

            return valid;
        }


        /// <summary>
        /// 检测参数合法性
        /// </summary>
        /// <returns></returns>
        protected bool CheckParamIsValid() 
        {
            //样品位置 要在 范围
            foreach(SampleCell sample in Samples)
            {
                if (sample.Enable)
                {                    
330
                    if(((sample.Position -  SampleRange)<0) || ((sample.Position+SampleRange)>= flyad.PosLen))
潘栩锋's avatar
潘栩锋 committed
331 332 333 334 335 336 337
                        return false;
                }
            }
            foreach(SampleFeature feature in Features)
            {
                if (feature.Enable)
                {                    
338
                    if(((feature.StartPos -  SearchRange)<0) || ((feature.EndPos+SearchRange)>= flyad.PosLen))
潘栩锋's avatar
潘栩锋 committed
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
                        return false;
                }
            }
            
            return true;
        }
        
        /// <summary>
        /// 样品取样,推送给thickm, 参数一定合法,不用检测
        /// </summary>
        /// <param name="direction"></param>
        public void Do(Misc.DIRECTION direction)
        {
            int[] dat;
            flyad.GetGrid(direction,0, flyad.PosLen/flyad.PosOfGrid, out dat);
            Do(direction, 0, dat);
        }

357
        bool CalGridOffset(SampleFeature psr, Misc.DIRECTION direction,int grid_start, int[] buf, out int grid_offset) 
潘栩锋's avatar
潘栩锋 committed
358
        {
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
            grid_offset = 0;
            //检测机架数据,当为空时,不能作相识性计算
            if (!mGageInfo.DataOK)
                return true;

            int pos1 = psr.StartPos;
            int pos2 = psr.EndPos;
            int posOfGrid = flyad.PosOfGrid;

            int grid1 = pos1 / posOfGrid;
            int grid2 = pos2 / posOfGrid;
            int grid_searchtol = SearchRange / posOfGrid;

            //获取相同方向的机架信息数据
            int index = (direction == Misc.DIRECTION.FORWARD) ? 0 : 1;
            int[] gagedata = null;
            mGageInfo.GetGageInfo(index, (asyncContext, retData) =>
            {
                var reponse = retData as GetGageInfoResponse;
                gagedata = reponse.Data;
            }, this);
潘栩锋's avatar
潘栩锋 committed
380 381


382 383 384 385 386
            //合格,查找最大相识性的点
            int grid_b = grid1 - grid_searchtol;
            int grid_e = grid2 + grid_searchtol;
            int grid_len = grid_e - grid_b + 1;
            int[] scanData = new int[grid_len];//这个方向的需要 特征查找范围内的数据,不用考虑 buf 不够 grid_len 
潘栩锋's avatar
潘栩锋 committed
387

388
            Array.Copy(buf, grid_b - grid_start, scanData, 0, grid_len);
潘栩锋's avatar
潘栩锋 committed
389

390 391 392 393
            double max_relvency = 0;
            int max_grid_offset = 0;

            for (int i = 0; i < grid_searchtol * 2; i++)
潘栩锋's avatar
潘栩锋 committed
394
            {
395 396
                double r = Misc.MyMath.Correl(gagedata, grid1, scanData, i, grid2 - grid1 + 1);
                if (r > max_relvency)
潘栩锋's avatar
潘栩锋 committed
397
                {
398 399 400 401 402 403
                    max_relvency = r;
                    max_grid_offset = i - grid_searchtol;
                }
            }
            psr.MaxRelevancy = max_relvency;
            psr.MaxOffset = max_grid_offset * posOfGrid;
潘栩锋's avatar
潘栩锋 committed
404

405 406 407 408 409 410 411 412 413 414 415
            if (max_relvency > 0.8) //相识度必须高于0.8
            {
                grid_offset = max_grid_offset;//位置修正
                return true;
            }
            else
            {
                //相似性太低,取样失败!!!
                return false;
            }
        }
416

417 418 419 420 421 422 423 424 425 426 427 428 429
        /// <summary>
        /// 设置这个方向 全部样品为失败
        /// </summary>
        /// <param name="direction"></param>
        void SetFailure(Misc.DIRECTION direction) 
        {
            for (int i = 0; i < Samples.Count(); i++)
            {
                SampleCell sample = Samples[i];
                var tempre = tempFilters[i];
                if ((directions[i] == direction) && (sample.Enable))
                {
                    tempre.Reset();
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
                    states[i] = SampleState.IsFailure;
                }
            }
        }
        /// <summary>
        /// 设置全部样品为失败
        /// </summary>
        void SetFailure()
        {
            for (int i = 0; i < Samples.Count(); i++)
            {
                SampleCell sample = Samples[i];
                var tempre = tempFilters[i];
                if (sample.Enable)
                {
                    tempre.Reset();
                    states[i] = SampleState.IsFailure;
447 448 449
                }
            }
        }
潘栩锋's avatar
潘栩锋 committed
450

451 452 453 454 455 456 457 458 459 460 461 462 463
        public bool HasSampleAd()
        {
            for (int i = 0; i < Samples.Count(); i++)
            {
                SampleCell sample = Samples[i];
                if (sample.Enable)
                {
                    if (sample.AD <= 0)
                        return false;
                }
            }
            return true;
        }
464 465 466 467 468 469 470 471 472 473 474 475 476 477
        enum GetSampleAdResult 
        {
            OK,
            /// <summary>
            /// 没有采集数据
            /// </summary>
            Invalid,
            /// <summary>
            /// AD值为0
            /// </summary>
            Zero,
            /// <summary>
            /// 滤波 异常
            /// </summary>
478
            FilterErr
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
        }
        GetSampleAdResult GetSampleAd(SampleCell sample, TempFilter2 tempre, int grid_start, int[] buf, int grid_offset, out int ad) 
        {
            //获取grid 数据
            int posOfGrid = flyad.PosOfGrid;
            int grid = sample.Position / posOfGrid + grid_offset;
            int grid_range = SampleRange / posOfGrid;
            int grid1 = grid - grid_range;
            int grid_len = grid_range * 2;

            int grid_b = grid1 - grid_start;
            int grid_e = grid_b + grid_len - 1;
            //计算平均值
            ad = Misc.MyMath.Avg(buf, grid_b, grid_e);

            if (!Misc.MyBase.ISVALIDATA(ad))//AD无效。。。异常,复位
            {
                ad = -1;
潘栩锋's avatar
潘栩锋 committed
497

498 499 500 501 502 503 504 505
                return GetSampleAdResult.Invalid;
            }
            else
            {
                int orgAd = ad;
                ad = tempre.CalSampleAD(orgAd, TimeSpan.FromMinutes(Window));//ad 滤波
                double diff = Math.Abs(orgAd - ad);
                if (IsCheckByPercent)
潘栩锋's avatar
潘栩锋 committed
506
                {
507
                    if (diff == 0)
潘栩锋's avatar
潘栩锋 committed
508
                    {
509 510 511 512 513 514 515 516 517 518

                    }
                    else if (ad == 0)
                    {
                        ad = -1;
                        return GetSampleAdResult.Zero;
                    }
                    else if (diff / ad >= ErrPercent) //大于2% 异常
                    {
                        return GetSampleAdResult.FilterErr;
潘栩锋's avatar
潘栩锋 committed
519 520 521 522
                    }
                }
                else
                {
523 524 525 526 527
                    if (diff >= ErrValue)
                    {
                        return GetSampleAdResult.FilterErr;
                    }
                }
潘栩锋's avatar
潘栩锋 committed
528
            }
529 530
            return GetSampleAdResult.OK;
        }
潘栩锋's avatar
潘栩锋 committed
531

532 533
        GetSampleAdResult SetSampleAds(Misc.DIRECTION direction, int grid_start, int[] buf, int grid_offset) 
        {
潘栩锋's avatar
潘栩锋 committed
534 535
            for (int i = 0; i < Samples.Count(); i++)
            {
536
                SampleCell sample = Samples[i];
潘栩锋's avatar
潘栩锋 committed
537
                var tempre = tempFilters[i];
538
                if ((directions[i] == direction) && (sample.Enable))
潘栩锋's avatar
潘栩锋 committed
539
                {
540 541 542
                    //获取滤波后的AD值
                    var ret = GetSampleAd(sample, tempre, grid_start, buf, grid_offset, out int ad);
                    if(ret == GetSampleAdResult.OK)
潘栩锋's avatar
潘栩锋 committed
543
                    {
544
                        sample.AD = ad;
545
                        states[i] = SampleState.Ok;
潘栩锋's avatar
潘栩锋 committed
546
                    }
547
                    else
潘栩锋's avatar
潘栩锋 committed
548
                    {
549 550

                        return ret;
潘栩锋's avatar
潘栩锋 committed
551
                    }
552 553 554 555
                }
            }
            return GetSampleAdResult.OK;
        }
556
        void UpdateSampleErrNo(string msg) 
557
        {
558
            this.warningSystem.Update(ERRNOs.ERRNO_SAMPLE_FATAL.Code, ERRNOs.ERRNO_SAMPLE_FATAL.Description, msg);
559
        }
560 561 562 563 564 565 566 567 568 569
        /// <summary>
        /// 样品取样,推送给thickm, 参数一定合法,不用检测
        /// </summary>
        /// <param name="direction">方向</param>
        /// <param name="grid_start">开始grid序号</param>
        /// <param name="buf">grid数据</param>
        public virtual void Do(Misc.DIRECTION direction, int grid_start, int[] buf)
        {

            if (CheckParamIsValid() == false)
570
            {
571
                UpdateSampleErrNo("ParamErr");
572
                return;
573
            }
574 575 576 577
            int grid_offset = 0;//经过相识性计算后的偏移量

            //获取这个方向全部样品AD
            var ret = SetSampleAds(direction, grid_start, buf, grid_offset);
578
            switch (ret)
579 580 581
            {
                case GetSampleAdResult.Zero:
                    {
582
                        UpdateSampleErrNo("ADZero");
583 584 585 586
                    }
                    break;
                case GetSampleAdResult.Invalid:
                    {
587
                        UpdateSampleErrNo("NoData");
588 589 590 591
                    }
                    break;
                case GetSampleAdResult.FilterErr:
                    {
592
                        UpdateSampleErrNo("FilterErr");
593 594 595
                    }
                    break;
            }
潘栩锋's avatar
潘栩锋 committed
596

597
            if (ret != GetSampleAdResult.OK)
598
            {
599 600
                //有问题,全部复位
                SetFailure(direction);
601
            }
602 603 604 605 606
            if (OK())
            {
                //全部都采集完成
                if (!IsErr())//没有异常
                {
607
                    Remove_ERRNO_SAMPLE();
608

609 610 611 612 613 614 615 616 617 618 619
                    //备份
                    last_sampleData = new SampleData();
                    last_sampleData.Time = DateTime.Now;
                    last_sampleData.SampleADs = new int[Samples.Count()];
                    for (int i = 0; i < Samples.Count(); i++)
                    {
                        last_sampleData.SampleADs[i] = Samples[i].AD;
                    }
                }
            }
            _end:
620
            SampleChangedEvent?.Invoke(this);
潘栩锋's avatar
潘栩锋 committed
621
        }
622 623
        void Remove_ERRNO_SAMPLE()
        {
624
            this.warningSystem.Remove(ERRNOs.ERRNO_SAMPLE_FATAL);
625
        }
626 627 628 629 630 631 632 633
        bool IsErr()
        {
            if (last_sampleData == null)
                return false;

            if (IsPercentErr())
            {
                //历史比较有问题
634
                UpdateSampleErrNo("PercentErr");
635 636 637 638 639 640 641 642 643 644

                //设置全部都是异常,重新测量
                SetFailure();
                last_sampleData = null;
                return true;
            }

            if (IsCrossErr())
            {
                //交叉比较有问题
645
                UpdateSampleErrNo("CrossErr");
646 647 648 649 650 651 652 653 654 655

                //设置全部都是异常,重新测量
                SetFailure();
                last_sampleData = null;
                return true;
            }

            return false;
        }

潘栩锋's avatar
潘栩锋 committed
656 657 658 659 660
        /// <summary>
        /// 检测是否成功
        /// </summary>
        /// <returns></returns>
        public virtual bool OK()
661 662 663 664 665 666 667 668 669
        {
            return !IsFailure();
        }

        /// <summary>
        /// 刚才报警了,采样失败
        /// </summary>
        /// <returns></returns>
        public bool IsFailure() 
潘栩锋's avatar
潘栩锋 committed
670 671 672
        {
            if (Enable)
            {
673
                for (int i = 0; i < Samples.Count(); i++)
674
                {
675
                    SampleCell sample = Samples[i];
676 677
                    if (sample.Enable)
                    {
678 679
                        if (states[i] != SampleState.Ok)
                            return true;
680 681
                    }
                }
潘栩锋's avatar
潘栩锋 committed
682
            }
683 684
            return false;
        }
潘栩锋's avatar
潘栩锋 committed
685

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
        /// <summary>
        /// 全部采集完成,与上次采集比较 大于2% 异常
        /// </summary>
        /// <returns></returns>
        bool IsPercentErr()
        {
            for (int i = 0; i < Samples.Count(); i++)
            {
                SampleCell sample = Samples[i];
                if (sample.Enable)
                {
                    int ad = sample.AD;
                    if (ad <= 0)//写错程序
                        break;
                    int lastAd = last_sampleData.SampleADs[i];
                    double diff = Math.Abs(ad - lastAd);
                    if (diff / ad > ErrPercent) //大于2% 异常
                    {
                        return true;
                    }
                }
            }
            return false;
潘栩锋's avatar
潘栩锋 committed
709 710
        }

711
        /// <summary>
712
        /// 全部采集完成,再做 交叉比较
713 714
        /// </summary>
        /// <returns></returns>
715
        bool IsCrossErr()
716
        {
717 718
            //交叉比较
            for (int i = 1; i < Samples.Count(); i++)
719
            {
720 721
                SampleCell sample = Samples[i];
                if (sample.Enable)
722
                {
723 724 725 726 727 728 729 730 731 732 733 734 735
                    double p = 1.0 * sample.AD / Samples[0].AD;
                    if (p <= 0)//写错程序
                        break;

                    int lastAdi = last_sampleData.SampleADs[i];
                    int lastAd0 = last_sampleData.SampleADs[0];
                    if (lastAd0 <= 0)//写错程序
                        break;

                    double last_p = 1.0 * lastAdi / lastAd0;
                    double diff = Math.Abs(last_p - p);

                    if (diff / p > CrossErrPercent) //大于2% 异常
736
                    {
737
                        return true;
738 739 740 741 742
                    }
                }
            }
            return false;
        }
潘栩锋's avatar
潘栩锋 committed
743 744 745
        /// <summary>
        /// 获取N秒的数据,
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
746 747
        /// <param name="idx">序号</param>
        /// <param name="buf">数据</param>
潘栩锋's avatar
潘栩锋 committed
748 749 750 751 752 753 754 755 756
        /// <returns></returns>
        public void DoFix(int idx, int[] buf)
        {
            if (idx >= Samples.Count())
                return;
            else if (idx < 0)
                return;

            int avg = Misc.MyMath.Avg(buf);
潘栩锋's avatar
潘栩锋 committed
757
            SampleCell sample = Samples[idx];
潘栩锋's avatar
潘栩锋 committed
758 759
            sample.AD = avg;

760 761

            SampleChangedEvent?.Invoke(this);
潘栩锋's avatar
潘栩锋 committed
762
        }
763

潘栩锋's avatar
潘栩锋 committed
764 765 766 767 768 769 770 771 772 773


        public event PropertyChangedEventHandler PropertyChanged;


        public void Apply()
        {
            //通知上层
            Save();
        }
774 775 776 777 778 779

        /// <summary>
        ///  返回 List(List(TempFilterData))
        /// </summary>
        /// <param name="asyncCB"></param>
        /// <param name="asyncContext"></param>
780
        public void GetTempFilterDatas(AsyncCBHandler asyncDelegate, object asyncContext) 
781 782
        {
            List<List<TempFilterData>> ret = new List<List<TempFilterData>>();
潘栩锋's avatar
潘栩锋 committed
783 784 785 786
            for (int i = 0; i < Samples.Count(); i++) {
                SampleCell sample = Samples[i];
                if (sample.Enable)
                    ret.Add(tempFilters[i].GetDatas());
787
            }
788
            asyncDelegate(asyncContext, ret);
789
        }
潘栩锋's avatar
潘栩锋 committed
790 791


潘栩锋's avatar
潘栩锋 committed
792
    }
793

794 795 796 797 798 799 800 801 802 803 804 805

    public class SampleData : INotifyPropertyChanged
    {
        public DateTime Time { get; set; }
        /// <summary>
        /// 样品采集AD值
        /// </summary>
        public int[] SampleADs { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
    }

806
    public delegate void SampleChangedEventHandler(GSample gsample);
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885

    public class GSampleJsonDb 
    {
        static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c =>
        {
            c.CreateMap<GSample, GSampleJsonDb>()
            .ForMember(s => s.Samples, opt =>
            {
                opt.MapFrom(s => Map_SampleCell2SampleCellParam(s.Samples));
            }).ForMember(s => s.Features, opt =>
            {
                opt.MapFrom(s => Map_SampleFeature2SampleFeatureParam(s.Features));
            })
            .ReverseMap()
            .ForMember(s => s.Samples, opt =>
            {
                opt.MapFrom(s => Map_SampleCellParam2SampleCell(s.Samples));
            })
            .ForMember(s => s.Features, opt =>
            {
                opt.MapFrom(s => Map_SampleFeatureParam2SampleFeature(s.Features));
            });
        }));
        static SampleCell[] Map_SampleCellParam2SampleCell(SampleCellParam[] sampleCellParams) {
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(sampleCellParams);
            return Newtonsoft.Json.JsonConvert.DeserializeObject<SampleCell[]>(json);
        }
        static SampleCellParam[] Map_SampleCell2SampleCellParam(SampleCell[] sampleCells)
        {
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(sampleCells);
            return Newtonsoft.Json.JsonConvert.DeserializeObject<SampleCellParam[]>(json);
        }

        static SampleFeature[] Map_SampleFeatureParam2SampleFeature(SampleFeatureParam[] sampleFeatureParams)
        {
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(sampleFeatureParams);
            return Newtonsoft.Json.JsonConvert.DeserializeObject<SampleFeature[]>(json);
        }
        static SampleFeatureParam[] Map_SampleFeature2SampleFeatureParam(SampleFeature[] sampleFeatures)
        {
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(sampleFeatures);
            return Newtonsoft.Json.JsonConvert.DeserializeObject<SampleFeatureParam[]>(json);
        }
        public static bool Load(GSample src, string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    string json = File.ReadAllText(filePath);
                    var p = JsonConvert.DeserializeObject<GSampleJsonDb>(json);
                    Mapper.Map(p, src);
                    return true;
                }
            }
            catch
            {
                //异常,没有json 解码失败
            }

            return false;
        }
        public static bool Save(GSample src, string filePath)
        {
            var p = Mapper.Map<GSampleJsonDb>(src);
            try
            {
                File.WriteAllText(filePath, JsonConvert.SerializeObject(p, Formatting.Indented));
                return true;
            }
            catch
            {
                //异常,没有json 编码失败

            }
            return false;

        }
        public bool Enable { get; set; } = true;
886

887
		public int Window { get; set; }
888
        public int SampleRange { get; set; } = 100;
889 890 891
        public bool IsCheckByPercent { get; set; } = true;
        public double ErrPercent { get; set; } = 2;
        public int ErrValue { get; set; } = 200;
892
        public double CrossErrPercent { get; set; } = 0.02;
893
        public SampleCellParam[] Samples { get; set; }
894
        public int SearchRange { get; set; } = 100;
895 896
        public SampleFeatureParam[] Features { get; set; }
    }
潘栩锋's avatar
潘栩锋 committed
897
}