using AutoMapper; using FLY.Thick.Base.Common; using FLY.Thick.Base.Server; using FLY.Thick.Blowing; using FLY.Thick.Blowing.Common; using FLY.Thick.Blowing.IService; using FLY.Thick.Blowing.Server.Model; using FlyADBase; using FObjBase; using FObjBase.Reflect; using Misc; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; namespace FLY.Thick.Blowing360.Server { public class GM_BlowingFix360 : GM_Base, IBlowingFixService { NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); const int MARKNO_PROFILE_ADD = 87; const int MARKNO_PROFILE_CHANGED = 88; #region 延时操作,markno const int MARKNO_CALFRAME = 2; #endregion #region IRenZiJiaService #region 分区设定 /// <summary> /// 加热通道数 /// </summary> public int ChannelCnt { get; set; } = 88; /// <summary> /// 分区数/加热通道数 /// </summary> public int BPC { get; set; } = 1; /// <summary> /// 风环螺丝数 /// </summary> public int NBolts => ChannelCnt * BPC; /// <summary> /// 复位时,探头测量的位置对应分区号 /// </summary> public int OrgBoltNo { get; set; } = 1; /// <summary> /// 第1个螺丝号 /// </summary> public int BoltNo1st = 1; /// <summary> /// 使用分区表 /// </summary> public bool IsUsedMap { get; set; } bool IsNeedMap() { if (IsUsedMap && Map != null && Map.Count() > 0) return true; else return false; } private BoltMapCell[] map; /// <summary> /// 分区表,必须保证不能为null /// </summary> public BoltMapCell[] Map { get { return map; } set { //检测是否不一样 if (!IsEquals(map, value)) { if (!IsValid(value)) { IsUsedMap = false; map = null; } else { map = value; } } } } #endregion /// <summary> /// 测厚仪类型, 追边 or 扫描 /// </summary> public BlowingType BType { get; } = BlowingType.Fix360; /// <summary> /// 测厚仪测量点位置方向:Left, Right (也就是三角形在左还是右) /// </summary> public bool IsProbeRight { get; set; } = true; /// <summary> /// 应用 /// </summary> public void Apply() { Save(); } [Push(typeof(RenZiJiaDataEventArgs))] public event EventHandler DataEvent; #endregion HistoryDb historyDb; BulkDb bulkDb; /// <summary> /// 人字架角度 & 膜走带位置检测 /// </summary> IBlowingDetectInServer mPDetect; DynArea mDynArea; BlowingFixProfileParam mProfileParam; /// <summary> /// 当前正在处理的 ADList 里面的数据.No /// </summary> int mADListToDoNo; /// <summary> /// 处理放入filminfo 的数据.No /// </summary> int mADListToDoNo_ToFilmInfo; /// <summary> /// 1s一个数据, /// </summary> RList<ADCell> mADList; class FRAME_INFO//一幅数据信息 { public DateTime StartTime;//开始时间 public DateTime EndTime;//结束时间 public int NoStartAD;//在AD列表 处理的数据开始点 public int NoEndAD;//在AD列表 处理的数据结束点 public DIRECTION direction;//当前幅数据,方向 public double velocity;//线速度 m/min public int rotationCnt;//人字架旋转次数 /// <summary> /// 对应数据库的 id /// </summary> public Int64? scandata_id = null; /// <summary> /// 分区数据 N*long /// </summary> public double[] frame; /// <summary> /// 经过分区表后的结果 /// </summary> public double[] frame_map; /// <summary> /// 推送出去的数据,也是数据库中的数据 /// </summary> public RenZiJiaDataEventArgs renZiJiaDataEventArgs; /// <summary> /// 推送出去的数据 被修改了 /// </summary> public bool renZiJiaDataEventArgsHasChanged = false; double frame_sum = 0; int frame_cnt = 0; public void SetNBolt(int nbolts) { frame = new double[nbolts]; for (int i = 0; i < nbolts; i++) { ClearFrameValue(i); } } void ClearFrameValue(int index) { frame[index] = double.NaN; } public void Clear() { for (int i = 0; i < frame.Count(); i++) { ClearFrameValue(i); } HasChanged = true; index_last = -1; frame_cnt = 0; frame_sum = 0; } public bool HasChanged = false;//数据被改变了!!!,是时候更新bulkdata /// <summary> /// 提交,完成一次操作。清除状态 /// </summary> public void Submit() { HasChanged = false; } int index_last = -1; public void SetFrameValue(int index, double value) { int nbolts = frame.Count(); if (index >= nbolts) return;//异常 else if (index < 0) return;//异常 else if (double.IsNaN(value)) return;//异常 if (index_last != index) { index_last = index; HasChanged = true; frame_cnt = 0; frame_sum = 0; } frame_sum += value; frame_cnt++; frame[index] = frame_sum / frame_cnt; } } RList<FRAME_INFO> mFrameInfoList; AD2ThkHandler Ad2Thk; void checkParamErr() { if (ChannelCnt < 10 || ChannelCnt > 160) { ChannelCnt = 44; } if (BPC < 1 || BPC > 10) { BPC = 2; } if (OrgBoltNo < 1 || OrgBoltNo > NBolts) { OrgBoltNo = 1; } if (!IsValid(Map)) { IsUsedMap = false; Map = null; } } /// <summary> /// 检测通过,返回true /// </summary> /// <returns></returns> bool IsValid(BoltMapCell[] mapCells) { bool map_err = false; bool g_o = false; bool g_n = false; if (mapCells == null) return true; //Map 检测 //OldNo,NewNo不能 <1 >NBolts //Map OldNo 必须从小到大环形排列 //Map NewNo 必须从小到大环形排列 for (int i = 0; i < mapCells.Count(); i++) { var mapCell = mapCells[i]; if (mapCell.NewNo < 1 || mapCell.NewNo > NBolts) { map_err = true; break; } if (mapCell.OldNo < 1 || mapCell.OldNo > NBolts) { map_err = true; break; } int i_next = i + 1; if (i_next >= mapCells.Count()) i_next = 0; var mapCell_next = mapCells[i_next]; if (mapCell.OldNo >= mapCell_next.OldNo) { if (!g_o) g_o = true; else { map_err = true; break; } } if (mapCell.NewNo >= mapCell_next.NewNo) { if (!g_n) g_n = true; else { map_err = true; break; } } } if (map_err) { return false; } else { return true; } } bool IsEquals(BoltMapCell c1, BoltMapCell c2) { if (c1 == c2) { return true; } if (c1 == null && c2 != null) return false; if (c1 != null && c2 == null) return false; if (c1.NewNo != c2.NewNo) return false; if (c1.OldNo != c2.OldNo) return false; return true; } bool IsEquals(BoltMapCell[] mapCells1, BoltMapCell[] mapCells2) { if (mapCells1 == mapCells2) return true; if (mapCells1 == null && mapCells2 != null) return false; if (mapCells1 != null && mapCells2 == null) return false; if (mapCells1.Count() != mapCells2.Count()) return false; //mapCells1 与 mapCells2 肯定都不是 null 且数量一样 for (int i = 0; i < mapCells1.Count(); i++) { var c1 = mapCells1[i]; var c2 = mapCells2[i]; if (!IsEquals(c1, c2)) return false; } return true; } /// <summary> /// /// </summary> /// <param name="flyad"></param> public GM_BlowingFix360() { GMState = CTRL_STATE.FIX; Load(); //检测参数 checkParamErr(); InitList(); } public void Init( FlyAD7 flyad, IBlowingDetectInServer blowingDetect, AD2ThkHandler ad2thk, DynArea dynarea, BlowingFixProfileParam profileParam, HistoryDb historyDb, BulkDb bulkDb ) { base.Init(flyad); this.mPDetect = blowingDetect; Ad2Thk = ad2thk; mDynArea = dynarea; mProfileParam = profileParam; this.historyDb = historyDb; //this.orgHistoryDb = orgHistoryDb; this.bulkDb = bulkDb; this.bulkDb.GetTempFrameAction = GetTempFrame; PropertyChanged += new PropertyChangedEventHandler(RenZiJiaFix_PropertyChanged); mFlyAD.TimeGridEvent += new FlyADBase.TimeGridEventHandler(flyad_TimeGridEvent); mPDetect.FilmInfoChangedEvent += new FilmInfoChangedEventHandler(mPDetect_FilmInfoChangedEvent); mPDetect.ClearEvent += new ClearEventHandler(mPDetect_ClearEvent); Misc.BindingOperations.SetBinding(mPDetect, nameof(mPDetect.FilmVelocity), mDynArea, nameof(mDynArea.FilmVelocity)); mProfileParam.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(mProfileParam.K)) { //重新计算当前幅数据 UpdateCurrFrame(); } }; //mDynArea.PropertyChanged += (s, e) => //{ // if (e.PropertyName == nameof(mDynArea.SampleAD)) // { // //重新计算当前幅数据 // UpdateCurrFrame(); // } //}; //记录调试数据 MarkDebugInit(); } void mPDetect_ClearEvent(object sender) { //没信号,清空所有数据!!! } /// <summary> /// 从1幅数据,获取头部,尾部,为于 ADList 的位置 /// </summary> /// <param name="frameinfo"></param> /// <param name="index_start"></param> /// <param name="index_end"></param> /// <returns>false 数据不存在</returns> bool GetFilmInfoADIndex(FRAME_INFO frameinfo, out int index_start, out int index_end) { index_start = mADList.No2Index(frameinfo.NoStartAD); index_end = mADList.No2Index(frameinfo.NoEndAD); if ((index_start < 0) || (index_end < 0) || (index_start >= mADList.Count) || (index_end >= mADList.Count)) { //数据已经不存在,删除 return false; } return true; } void mPDetect_FilmInfoChangedEvent(object sender, FilmInfoChangedEventArgs e) { var ret = ADListFastSearchIndex(e.Time, out int idx); switch (ret) { case ADListFastSearchIndexResult.Before://发送在过去 { mADListToDoNo = mADList.Index2No(0); mADListToDoNo_ToFilmInfo = mADListToDoNo; } break; case ADListFastSearchIndexResult.Now://发生在列表时间内 { mADListToDoNo = mADList.Index2No(idx); mADListToDoNo_ToFilmInfo = mADListToDoNo; } break; case ADListFastSearchIndexResult.Future: { //未来的,不处理 } break; } } void RenZiJiaFix_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(NBolts)) { //所有数据删除 mFrameInfoList.Clear(); } else if (e.PropertyName == nameof(OrgBoltNo)) { //TODO 只处理3幅图 int idx = mFrameInfoList.Count - 3; if (idx < 0) idx = 0; if (idx >= mFrameInfoList.Count) return; mADListToDoNo_ToFilmInfo = mFrameInfoList[idx].NoStartAD; } } BulkDbTempFrameChangedEventArgs GetTempFrame() { if (mFrameInfoList.Count() > 0) { var frameInfo = mFrameInfoList.Last(); var thicks = IsNeedMap() ? frameInfo.frame_map : frameInfo.frame; return new BulkDbTempFrameChangedEventArgs() { Time = frameInfo.StartTime, EndTime = frameInfo.EndTime, StartIndex = 0, D = thicks }; } else { return new BulkDbTempFrameChangedEventArgs(); } } #region 记录测试数据 DateTime markdebug_dt = DateTime.MinValue; void MarkDebugInit() { if (markdebug_dt == DateTime.MinValue) markdebug_dt = DateTime.Now; //启动1分钟定时器 FObjBase.PollModule.Current.Poll_Config( FObjBase.PollModule.POLL_CONFIG.ADD, () => { //mPDetect.GetSignList(markdebug_dt, (asyncContext, retData) => //{ // var reponse = retData as GetSignListReponse; // var cells = reponse.datas; // if (cells.Count > 0) // { // orgHistoryDb.AddSignData( // new Lc_Sign() // { // Time = cells.First().Time, // Signs = cells.ToArray() // }); // } //}, null); //mPDetect.GetRollList(markdebug_dt, (asyncContext, retData) => //{ // var reponse = retData as GetRollListReponse; // var cells = reponse.datas; // if (cells.Count > 0) // { // orgHistoryDb.AddRollData( // new Lc_Roll() // { // Time = cells.First().dt, // Signs = cells.ToArray() // }); // } //}, null); this.GetADList(markdebug_dt, (asyncContext, retData) => { var reponse = retData as GetADListReponse; var cells = reponse.datas; if (cells.Count > 0) { var thicks = cells.Select(c => c.thk).ToArray(); historyDb.AddTrendData( new Lc_TrendData() { Time = cells.First().dt, K = mProfileParam.K, Thicks = thicks }); } }, null); markdebug_dt = DateTime.Now; }, TimeSpan.FromMinutes(1)); } #endregion void UpdateCurrFrame() { FObjBase.PollModule.Current.Poll_JustOnce( new FObjBase.PollModule.PollHandler(delegate () { if (mFrameInfoList.Count > 0) { mADListToDoNo_ToFilmInfo = mFrameInfoList.Last().NoStartAD; } }), this, MARKNO_CALFRAME); } TimeSpan datOf1s_ts = TimeSpan.Zero; TimeSpan datOf1s_interval = TimeSpan.FromSeconds(1); List<int> datOf1s = new List<int>(); void flyad_TimeGridEvent(object sender, FlyADBase.TimeGridEventArgs e) { bool issample = false; TimeSpan ts = e.Ts;//准确 DateTime dt = e.Time;//准确 int[] data = e.Data; DateTime datOf100ms_dt = DateTime.MinValue; for (int i = 0; i < data.Length; i++) { if (issample)//采样中,数据都是无效的 { datOf1s.Add(Misc.MyBase.NULL_VALUE); } else if (data[i] > UInt16.MaxValue) { datOf1s.Add(Misc.MyBase.NULL_VALUE); } else if (data[i] < 0) { datOf1s.Add(Misc.MyBase.NULL_VALUE); } else { datOf1s.Add(data[i]); } datOf1s_ts = datOf1s_ts + ts; if (datOf100ms_dt == DateTime.MinValue) datOf100ms_dt = dt; else datOf100ms_dt = datOf100ms_dt + ts; if (datOf1s_ts >= datOf1s_interval)//1s 一个数据 { datOf1s_ts = datOf1s_ts - datOf1s_interval; int avgad = Misc.MyBase.NULL_VALUE; if (datOf1s.Count() > 0) { avgad = Misc.MyMath.Avg(datOf1s.ToArray()); datOf1s.Clear(); } else if (mADList.Count() > 0) { avgad = mADList.Last().Ad; } mADList.RAdd( new ADCell() { Time = DateTime.Now, Ad = avgad }); } } } private void InitList()//初始化列表 { if (mADList == null) { mADList = new RList<ADCell>(4000); mADListToDoNo = mADList.GetLastNo(); mADListToDoNo_ToFilmInfo = mADListToDoNo; } if (mFrameInfoList == null) mFrameInfoList = new RList<FRAME_INFO>(6); } //复位 void Clear() { if (mADList != null) mADList.Clear(); if (mFrameInfoList != null) { mFrameInfoList.Clear(); } } int Angle2BoltIndex(double angle) { if (angle < 0) { angle += 360; } int boltindex = (int)(OrgBoltNo - BoltNo1st + angle * NBolts / 360); if (boltindex >= NBolts) { boltindex -= NBolts; } else if (boltindex < 0)//不应该发生,可能是 OrgBoltNo 出错了。 { boltindex += NBolts; } return boltindex; } enum ADListFastSearchIndexResult { /// <summary> /// 时间点在列表以前; /// </summary> Before = -1, /// <summary> /// 时间点在列表中; /// </summary> Now = 0, /// <summary> /// 时间点在列表的未来; /// </summary> Future = 1 } /// <summary> /// 找到在 dt 前最近的 ADList 序号; /// 当ADList 没有数据,返回 Future; /// 已知AD列表每个数据之间的时间差,快速推断结果; /// </summary> /// <param name="dt"></param> /// <param name="index"></param> /// <returns></returns> ADListFastSearchIndexResult ADListFastSearchIndex(DateTime dt, out int index) { index = 0; if (mADList.Count <= 0)//列表没有数据, 只能当它在未来 return ADListFastSearchIndexResult.Future; if (dt > mADList.Last().Time) return ADListFastSearchIndexResult.Future; else if (dt < mADList.First().Time) return ADListFastSearchIndexResult.Before; else { int offset = (int)((mADList.Last().Time - dt).TotalSeconds / datOf1s_interval.TotalSeconds); index = mADList.Count - offset - 1;//大约在这个位置附近 //安全限制 if (index >= mADList.Count) index = mADList.Count() - 1; else if (index < 0) index = 0; if (mADList[index].Time == dt) { //已经找到就是它!!!! } else if (mADList[index].Time > dt) { while (true) { index--; if (index <= 0) { index = 0;//最前面一个了 break; } if (mADList[index].Time <= dt) { //找到了 break; } } } else { while (true) { index++;//测试一下 if (index >= mADList.Count) { //到顶了,不找了 index--; break; } else if (mADList[index].Time == dt) { //找到了,就是它 break; } else if (mADList[index].Time > dt) { //上一个小于,现在大于,上一个就对了 index--; break; } } } return ADListFastSearchIndexResult.Now; } } void OnPoll_UpdateADList() { int adlist_index = mADList.No2Index(mADListToDoNo); if (adlist_index >= mADList.Count) return;//没有数据需要处理 if (adlist_index < 0) adlist_index = 0; for (int i = adlist_index; i < mADList.Count; i++) { mADListToDoNo = mADList.Index2No(i); if (!OnPoll_UpdateADList_Edge(i)) return; } mADListToDoNo = mADList.Index2No(mADList.Count); } bool OnPoll_UpdateADList_Edge(int idx) { FilmInfo filminfo; int ret = mPDetect.GetFilmInfo(out filminfo, mADList[idx].Time, 2.3, 0); if (ret == 1)//发生在未来 { return false; } if (filminfo == null)//异常,FilmPosH 错误 { return false; } if (mADListToDoNo != mADList.Index2No(idx))//触发了事件 { return false; } ADCell adcell = mADList[idx]; adcell.Angles.Clear(); adcell.Angles.Add(filminfo.angle1); adcell.Direction = filminfo.direction; adcell.Velocity = filminfo.filmVelocity; adcell.RotationCnt = filminfo.rotationCnt; adcell.InCV = filminfo.inCV; return true; } /// <summary> /// 状态不一样,人字架已经转了新一圈,需要增加新一幅数据 /// </summary> /// <param name="adcell"></param> /// <param name="frameinfo"></param> /// <returns></returns> bool FrameInfoCheckToNew(ADCell adcell, FRAME_INFO frameinfo) { if (//(adcell.Direction != frameinfo.direction) ||//永远是正方向。。。。不可能执行 (adcell.RotationCnt != frameinfo.rotationCnt)) //(Math.Abs(adcell.velocity - frameinfo.velocity) > 2)) { return true; } else { return false; } } /// <summary> /// 输出的数据都必须是稳定,可靠的。 生成一幅幅测厚仪数据!!!!!!!!!!!! /// </summary> void OnPoll_UpdateFrameInfo() { int adlist_index = mADList.No2Index(mADListToDoNo_ToFilmInfo);//当前在处理的 数据点 if (adlist_index >= mADList.Count) return;//没有数据需要处理 if (adlist_index < 0)//全部都要处理 adlist_index = 0; //当没有任何一幅数据时, frameinfo_index = mFrameInfoList.Count = 0 int frameinfo_index = Math.Max(mFrameInfoList.Count - 1, 0); //查找adlist_index 属于哪个frameinfo; //当找到,清空里面的.frame,一切重新开始!!! //当不能找到,说明只是接着上次的处理而已,不需要重新开始 for (int i = 0; i < mFrameInfoList.Count; i++) { int index_start; int index_end; FRAME_INFO frameinfo = mFrameInfoList[i]; if (!GetFilmInfoADIndex(frameinfo, out index_start, out index_end)) { //数据已经不存在,删除 mFrameInfoList.RemoveAt(i); i--; continue; } if (adlist_index <= index_end) { //要处理的数据点,位于 这幅数据 (frameinfo); 重新计算整幅数据 frameinfo_index = i; //adlist_index = mADList.No2Index(frameinfo.NoStartAD); break; } } int adlist_todo_index = mADList.No2Index(mADListToDoNo);//已经成功获取完位置信息的数据尽头 for (int i = adlist_index; (i < mADList.Count && i < adlist_todo_index); i++) { ADCell adcell = mADList[i]; //mADListToDoNo_ToFilmInfo = mADList.Index2No(i); FRAME_INFO frameinfo; //-------------------------------------------------------------------------------------------------------- //条件检测 if (frameinfo_index >= mFrameInfoList.Count)//根本没数据,新建 { frameinfo = new FRAME_INFO(); frameinfo.StartTime = adcell.Time; frameinfo.EndTime = adcell.Time; frameinfo.direction = adcell.Direction; frameinfo.velocity = adcell.Velocity; frameinfo.rotationCnt = adcell.RotationCnt; frameinfo.NoStartAD = mADList.Index2No(i); frameinfo.NoEndAD = mADList.Index2No(i); frameinfo.SetNBolt(NBolts); mFrameInfoList.RAdd(frameinfo); frameinfo_index = mFrameInfoList.Count - 1; } else { frameinfo = mFrameInfoList[frameinfo_index]; if (i <= mADList.No2Index(frameinfo.NoEndAD)) { //当为新数据, i应该>mADList.No2Index(frameinfo.NoEndAD) //能进这里,证明是要重新计算 //清空数据,重新来过 frameinfo.StartTime = adcell.Time; frameinfo.EndTime = adcell.Time; frameinfo.direction = adcell.Direction; frameinfo.velocity = adcell.Velocity; frameinfo.rotationCnt = adcell.RotationCnt; frameinfo.NoStartAD = mADList.Index2No(i); frameinfo.NoEndAD = mADList.Index2No(i); frameinfo.Clear(); } } //-------------------------------------------------------------------------------------------------------- if (FrameInfoCheckToNew(adcell, frameinfo)) { //重新分区 if (IsNeedMap()) { //上面已经检查了 Map == null 的情况 Dictionary<int, int> m = new Dictionary<int, int>(); for (int j = 0; j < Map.Count(); j++) m.Add(Map[j].OldNo - 1, Map[j].NewNo - 1); frameinfo.frame_map = Misc.MyMath.Map(frameinfo.frame, m); } //更新数据库内容 { double[] frame; List<BoltMapCell> map; if (IsNeedMap()) { //上面已经检查了 Map == null 的情况 frame = frameinfo.frame_map; map = new List<BoltMapCell>(); foreach (var m in Map) map.Add(m.Clone()); } else { frame = frameinfo.frame; map = null; } //限制小数点 for (int j = 0; j < frame.Count(); j++) { if (!double.IsNaN(frame[j])) frame[j] = Math.Round(frame[j], 2); } frameinfo.renZiJiaDataEventArgs = new RenZiJiaDataEventArgs() { Time = frameinfo.StartTime, EndTime = frameinfo.EndTime, IsBackw = frameinfo.direction == DIRECTION.BACKWARD, RPeriod = mPDetect.RenZiJiaPeriod, RCnt = frameinfo.rotationCnt, OrgBoltNo = OrgBoltNo, RAngle = 360, FilmLength = Math.Round(mPDetect.FilmLength, 2), FilmVelocity = Math.Round(mPDetect.FilmVelocity, 2), K = Math.Round(mProfileParam.K, 3), Thicks = frame, Boltmap = map }; frameinfo.renZiJiaDataEventArgsHasChanged = true; } //更新到下一个frameinfo frameinfo_index++; i--; continue; } double thk = Ad2Thk(adcell.Ad); frameinfo.SetFrameValue(Angle2BoltIndex(adcell.Angles.First()), thk); frameinfo.EndTime = adcell.Time; frameinfo.NoEndAD = mADList.Index2No(i); } mADListToDoNo_ToFilmInfo = mADListToDoNo; //检测数据更新情况,放入bulkdata for (int i = 0; i < mFrameInfoList.Count; i++) { FRAME_INFO frameinfo = mFrameInfoList[i]; if (frameinfo.HasChanged)//数据检测过,需要更新bulkdata里面的数据, 大部分发生在扫描过程中,还没结束一幅图 { //重新分区 if (IsNeedMap()) { //上面已经检查了 Map == null 的情况 Dictionary<int, int> m = new Dictionary<int, int>(); for (int j = 0; j < Map.Count(); j++) m.Add(Map[j].OldNo - 1, Map[j].NewNo - 1); frameinfo.frame_map = Misc.MyMath.Map(frameinfo.frame, m); } //TODO 更新即时图!!!! //var thicks = IsNeedMap() ? frameinfo.frame_map : frameinfo.frame; } } //检查数据是否被修改, 推送出去!!!!! if (mFrameInfoList.Count() > 0) { FRAME_INFO frameinfo = mFrameInfoList.Last(); if (frameinfo.HasChanged) { var thicks = IsNeedMap() ? frameinfo.frame_map : frameinfo.frame; //TODO, 推送的数据,可能太多了!!!! bulkDb.SetTempFrame(frameinfo.StartTime, frameinfo.EndTime, 0, thicks); } } foreach (var frameinfo in mFrameInfoList) { frameinfo.Submit(); } #region sqlite3 历史数据保存 if (mFrameInfoList.Any((frameinfo) => frameinfo.renZiJiaDataEventArgsHasChanged)) { //下辊检测 if (historyDb.localDb.IsProfileFinished) { AddProfile(); } } //检测数据更新情况,放入数据库, 数据不能被修改 RenZiJiaDataEventArgs renZiJiaDataEventArgs = null;//当数据被修改,推送事件!!!,当只有最后一幅图被推送 foreach (var frameinfo in mFrameInfoList) { if (frameinfo.renZiJiaDataEventArgsHasChanged) { frameinfo.renZiJiaDataEventArgsHasChanged = false; if (frameinfo.scandata_id == null) { if (frameinfo.renZiJiaDataEventArgs.FilmVelocity < 2) { //异常 continue; } //添加数据 var lc_scandata = Lc_AutoMapperProfile.Mapper.Map<Lc_ScanData>(frameinfo.renZiJiaDataEventArgs); historyDb.AddScanData(lc_scandata); frameinfo.scandata_id = lc_scandata.ID; renZiJiaDataEventArgs = frameinfo.renZiJiaDataEventArgs; } } } #endregion //当数据被修改,只推送最后一次的数据 if (renZiJiaDataEventArgs != null) DataEvent?.Invoke(this, renZiJiaDataEventArgs); } protected override void OnPoll() { OnPoll_UpdateADList(); OnPoll_UpdateFrameInfo(); } public override void Start() { //AD盒有没断开,也能触发,一直触发中!!! IsRunning = true; #region sqlite3 历史数据保存 CheckProfile(); mProfileParam.PropertyChanged += MProfileParam_PropertyChanged; #endregion FObjBase.PollModule.Current.Poll_Config( FObjBase.PollModule.POLL_CONFIG.ADD, onpoll_func, TimeSpan.FromSeconds(1)); } #region sqlite3 历史数据保存 string[] profile_propertynames_add = new string[]{ nameof(BlowingFixProfileParam.PName), nameof(BlowingFixProfileParam.OrderNo), nameof(BlowingFixProfileParam.Number) }; string[] profile_propertynames_update = new string[]{ nameof(BlowingFixProfileParam.Target), nameof(BlowingFixProfileParam.TolerancePercent) }; void CheckProfile() { if (historyDb.localDb.IsProfileFinished) { //复位 膜纵向位置 AddProfile(); } else { if (historyDb.localDb.CurrProfile != null) { Db_Profile dB_Profile = historyDb.localDb.CurrProfile; if ((dB_Profile.PName != mProfileParam.PName) || (dB_Profile.OrderNo != mProfileParam.OrderNo) || (dB_Profile.Number != mProfileParam.Number)) { AddProfile(); } else { //继续上一次生产!!!! UpdateProfile(); } } else { //异常 AddProfile(); } } } void AddProfile() { historyDb.AddProfile(new Db_Profile() { PName = mProfileParam.PName, OrderNo = mProfileParam.OrderNo, Number = mProfileParam.Number, Target = mProfileParam.Target, TolerancePercent = mProfileParam.TolerancePercent, StartTime = DateTime.Now, EndTime = DateTime.Now }); } void UpdateProfile() { historyDb.UpdateProfile(new Db_Profile() { PName = mProfileParam.PName, OrderNo = mProfileParam.OrderNo, Number = mProfileParam.Number, Target = mProfileParam.Target, TolerancePercent = mProfileParam.TolerancePercent, }); } private void MProfileParam_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (profile_propertynames_add.Contains(e.PropertyName)) { FObjBase.PollModule.Current.Poll_JustOnce( () => { if (!historyDb.localDb.IsProfileFinished) { historyDb.FinishProfile(); } AddProfile();//新 }, this, MARKNO_PROFILE_ADD); } else if (profile_propertynames_update.Contains(e.PropertyName)) { FObjBase.PollModule.Current.Poll_JustOnce( () => { UpdateProfile();//修改 }, this, MARKNO_PROFILE_CHANGED); } } #endregion string file_path = "blowingfix360.json"; bool Load() { return BlowingFix360JsonDb.Load(this, file_path); } bool Save() { return BlowingFix360JsonDb.Save(this, file_path); } /// <summary> /// 获取 厚度列表 /// </summary> /// <param name="begin">开始时间</param> /// <param name="asyncDelegate"></param> /// <param name="asyncContext"></param> [Call(typeof(GetADListReponse))] public void GetADList(DateTime begin, AsyncCBHandler asyncDelegate, object asyncContext) { var p = new GetADListReponse { datas = mADList.FindAll(a => a.Time >= begin).Select(a => new ADSingle() { dt = a.Time, thk = Ad2Thk(a.Ad) }).ToList() }; asyncDelegate(asyncContext, p); } } public class BlowingFix360JsonDb { static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c => { c.CreateMap<GM_BlowingFix360, BlowingFix360JsonDb>().ReverseMap(); })); public static bool Load(GM_BlowingFix360 src, string file_path) { if (File.Exists(file_path)) { try { string json = File.ReadAllText(file_path); var jsonDb = JsonConvert.DeserializeObject<BlowingFix360JsonDb>(json); Mapper.Map(jsonDb, src); return true; } catch { //异常,没有json 解码失败 } } return false; } public static bool Save(GM_BlowingFix360 src, string file_path) { try { var jsonDb = Mapper.Map<BlowingFix360JsonDb>(src); string json = JsonConvert.SerializeObject(jsonDb, Formatting.Indented); File.WriteAllText(file_path, json); return true; } catch { //异常,没有json 编码失败 } return false; } public int ChannelCnt = 88; public int BPC = 1; public int OrgBoltNo = 1; public bool IsUsedMap; public BoltMapCell[] Map; public bool IsProbeRight = true; public bool IsUsedEncoder = false; } }