using AutoMapper;
using FLY.Thick.Base.Common;
using FLY.Thick.Base.Server;
using FLY.Thick.Blowing.Common;
using FLY.Thick.Blowing.IService;
using FLY.Thick.Blowing.Server.Model;
using FlyADBase;
using FObjBase;
using FObjBase.Reflect;
using MathNet.Numerics.LinearAlgebra.Double;
using Misc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
namespace FLY.Thick.Blowing.Server
{
///
///
///
public class GM_BlowingFix : GM_Base, IBlowingFixService
{
NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
const int MARKNO_PROFILE_ADD = 87;
const int MARKNO_PROFILE_CHANGED = 88;
//OrgHistoryDb orgHistoryDb;
HistoryDb historyDb;
BulkDb bulkDb;
#region 延时操作,markno
const int MARKNO_CALFRAME = 2;
#endregion
///
/// 人字架角度 & 膜走带位置检测
///
public BlowingDetect mPDetect;
#region IRenZiJiaService
#region 分区设定
///
/// 加热通道数
///
public int ChannelCnt { get; set; } = 88;
///
/// 分区数/加热通道数
///
public int BPC { get; set; } = 1;
///
/// 风环螺丝数
///
public int NBolts => ChannelCnt * BPC;
///
/// 复位时,探头测量的位置对应分区号
///
public int OrgBoltNo { get; set; } = 1;
///
/// 第1个螺丝号
///
public int BoltNo1st = 1;
///
/// 使用分区表
///
public bool IsUsedMap { get; set; }
bool IsNeedMap()
{
if (IsUsedMap && Map != null && Map.Count() > 0)
return true;
else
return false;
}
private BoltMapCell[] map;
///
/// 分区表,必须保证不能为null
///
public BoltMapCell[] Map
{
get { return map; }
set
{
//检测是否不一样
if (!IsEquals(map, value))
{
if (!IsValid(value))
{
IsUsedMap = false;
map = null;
}
else
{
map = value;
}
}
}
}
#endregion
///
/// 测厚仪类型, 追边 or 扫描
///
public BlowingType BType { get; } = BlowingType.Fix;
///
/// 测厚仪测量点位置方向:Left, Right (也就是三角形在左还是右)
///
public bool IsProbeRight { get; set; } = true;
///
/// 应用
///
public void Apply()
{
Save();
}
[Push(typeof(RenZiJiaDataEventArgs))]
public event EventHandler DataEvent;
#endregion
#region 吹膜定点解方程用
///
/// 测量模式, 决定是否解方程
///
public MeasureMode MMode { get; set; } = MeasureMode.Edge;
///
/// 膜宽 单位 mm
///
public int FilmWidth { get; set; } = 1500;
///
/// 探头所在膜的横向位置 单位 mm
///
public int FilmPosH { get; set; } = 70;
#endregion
DynArea mDynArea;
BlowingFixProfileParam mProfileParam;
///
/// 当前正在处理的 ADList 里面的数据.No
///
int mADListToDoNo;
///
/// 处理放入filminfo 的数据.No
///
int mADListToDoNo_ToFilmInfo;
///
/// 1s一个数据,
///
RList mADList;
///
/// 1条方程
///
class Formula
{
///
/// n元方程
///
public int n;
///
/// 方程 xi前面的 ai
///
public double[] ai;
///
/// 方程 y 值
///
public double y;
public Formula(int no_x)
{
int i;
n = no_x;
ai = new double[no_x];
for (i = 0; i < n; i++) ai[i] = 0;
y = 0;
}
public bool AddData(IEnumerable idxs, double thk)
{
foreach (int idx in idxs)
if ((idx < 0) || (idx >= n)) return false;
foreach (int idx in idxs)
ai[idx]++;
y += thk;
return true;
}
}
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;//人字架旋转次数
///
/// 对应数据库的 id
///
public Int64? scandata_id = null;
///
/// 分区数据 N*long
///
public double[] frame;
///
/// 经过分区表后的结果
///
public double[] frame_map;
///
/// 推送出去的数据,也是数据库中的数据
///
public RenZiJiaDataEventArgs renZiJiaDataEventArgs;
///
/// 推送出去的数据 被修改了
///
public bool renZiJiaDataEventArgsHasChanged = false;
double frame_sum = 0;
int frame_cnt = 0;
static int virtual_nbolts = 88;
static List virtual_formulas = new List();
static void UpdateVirtualFormulas()
{
virtual_formulas.Clear();
for (int i = 0; i < virtual_nbolts; i++)
{
int boltindex1 = i;
int boltindex2 = i + 1;
if (boltindex2 >= virtual_nbolts)
boltindex2 = 0;
Formula fm = new Formula(virtual_nbolts);
fm.ai[boltindex1] = 1;
fm.ai[boltindex2] = -1;
virtual_formulas.Add(fm);
}
}
static FRAME_INFO()
{
UpdateVirtualFormulas();
}
public void SetNBolt(int nbolts)
{
frame = new double[nbolts];
appeared = new bool[nbolts];
for (int i = 0; i < nbolts; i++)
{
ClearFrameValue(i);
}
}
void ClearFrameValue(int index)
{
frame[index] = double.NaN;
appeared[index] = false;
}
public void Clear()
{
for (int i = 0; i < frame.Count(); i++)
{
ClearFrameValue(i);
}
IsValid = true;
HasChanged = true;
index_last = -1;
frame_cnt = 0;
frame_sum = 0;
mFormulas.Clear();
last_solvedt = DateTime.MinValue;
isTimeToSolve = false;
canSolve = false;
}
public bool HasChanged = false;//数据被改变了!!!,是时候更新bulkdata
public bool IsValid = true;//是合法数据
///
/// 提交,完成一次操作。清除状态
///
public void Submit()
{
HasChanged = false;
}
public void CheckForValid()
{
if (rotationCnt == 0)//旋转次数=0,肯定是不完整的数据
{
HasChanged = true;
IsValid = false;
return;
}
//所有的数据都应该大于10
for (int i = 0; i < frame.Count(); i++)
{
if (!double.IsNaN(frame[i]))
{
if (frame[i] < 10.0)
{
HasChanged = true;
IsValid = false;
return;
}
}
}
}
///
/// 上一次解方程的时间
///
DateTime last_solvedt = DateTime.MinValue;
///
/// 是时候解方程
///
bool isTimeToSolve = false;
///
/// 方程多了,能解方程
///
bool canSolve = false;
///
/// 每个区号,是否有出现
///
bool[] appeared;
///
/// 方程组
///
List mFormulas = new List();
public void SolveFormula()
{
if (!canSolve)//没有新方程,没法解
return;
int nbolts = frame.Count();
if (virtual_nbolts != nbolts)
{
virtual_nbolts = nbolts;
UpdateVirtualFormulas();
}
//TODO 能否解得方程检查
int nrow = mFormulas.Count() + virtual_formulas.Count();
//if (nrow < NBolts) return;
//Console.WriteLine("Total get {0} formular", nrow);
//转换为 DenseMatrix 与 DenseVector
DenseMatrix matrixA = new DenseMatrix(nrow, nbolts);
DenseMatrix matrixAT = new DenseMatrix(nbolts, nrow);
DenseVector vectorB = new DenseVector(nrow);
int rowindex = 0;
foreach (Formula fm in mFormulas)
{
matrixA.SetRow(rowindex, fm.ai);
matrixAT.SetColumn(rowindex, fm.ai);
vectorB[rowindex] = fm.y;
rowindex++;
}
foreach (Formula fm in virtual_formulas)
{
matrixA.SetRow(rowindex, fm.ai);
matrixAT.SetColumn(rowindex, fm.ai);
vectorB[rowindex] = fm.y;
rowindex++;
}
DenseMatrix ATA = (DenseMatrix)matrixA.TransposeThisAndMultiply(matrixA);
DenseVector ATB = (DenseVector)matrixA.TransposeThisAndMultiply(vectorB);
DenseVector X = (DenseVector)ATA.Solve(ATB);
for (int i = 0; i < nbolts; i++)
{
double d = (appeared[i]) ? X[i] : double.NaN;
frame[i] = d;
}
HasChanged = true;
isTimeToSolve = false;
canSolve = false;
}
///
/// 检查是否需要更新
///
public void CheckToSolveFormula()
{
if (isTimeToSolve)
{
SolveFormula();
}
}
int index_last = -1;
public void SetFrameValue(int index, double value, DateTime dt)
{
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;
}
///
/// 解方程方式更新 frame
///
///
///
///
public void SetFrameValue(IEnumerable indexs, double value, DateTime dt)
{
int nbolts = frame.Count();
foreach (int index in indexs)
{
if (index >= nbolts)
return;//异常
else if (index < 0)
return;//异常
}
if (double.IsNaN(value))
return;//异常
Formula fm = new Formula(nbolts);
fm.AddData(indexs, value);
mFormulas.Add(fm);
foreach (int index in indexs)
appeared[index] = true;
canSolve = true;
//5秒解一次方程
if ((index_last != indexs.First()) && ((dt - last_solvedt) >= TimeSpan.FromSeconds(5)))
{
index_last = indexs.First();
last_solvedt = dt;
isTimeToSolve = true;
}
}
}
RList mFrameInfoList;
AD2ThkHandler Ad2Thk;
void checkParamErr()
{
if (ChannelCnt < 20 || ChannelCnt > 160)
{
ChannelCnt = 44;
}
if (BPC < 1 || BPC > 4)
{
BPC = 2;
}
if (OrgBoltNo < 1 || OrgBoltNo > NBolts)
{
OrgBoltNo = 1;
}
if (!IsValid(Map))
{
IsUsedMap = false;
Map = null;
}
}
///
/// 检测通过,返回true
///
///
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;
}
///
///
///
///
public GM_BlowingFix(FlyAD7 flyad)
: base(flyad)
{
GMState = CTRL_STATE.FIX;
mPDetect = new BlowingDetect();
mPDetect.Load();
Load();
//检测参数
mPDetect.CheckParamErr();
checkParamErr();
InitList();
PropertyChanged += new PropertyChangedEventHandler(RenZiJiaFix_PropertyChanged);
mPDetect.FilmInfoChangedEvent += new FilmInfoChangedEventHandler(mPDetect_FilmInfoChangedEvent);
mPDetect.ClearEvent += new ClearEventHandler(mPDetect_ClearEvent);
mFlyAD.TimeGridEvent += new FlyADBase.TimeGridEventHandler(flyad_TimeGridEvent);
mPDetect.Init(flyad);
}
void mPDetect_ClearEvent(object sender)
{
//没信号,清空所有数据!!!
Clear();
}
///
/// 从1幅数据,获取头部,尾部,为于 ADList 的位置
///
///
///
///
/// false 数据不存在
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;
}
else if ((e.PropertyName == nameof(FilmWidth)) || (e.PropertyName == nameof(FilmPosH)) || (e.PropertyName == nameof(MMode)))
{
//重新计算当前幅数据
UpdateCurrFrame();
}
}
public void Init(
AD2ThkHandler ad2thk, DynArea dynarea,
BlowingFixProfileParam profileParam,
HistoryDb historyDb,
BulkDb bulkDb
)
{
Ad2Thk = ad2thk;
mDynArea = dynarea;
mProfileParam = profileParam;
this.historyDb = historyDb;
//this.orgHistoryDb = orgHistoryDb;
this.bulkDb = bulkDb;
this.bulkDb.GetTempFrameAction = GetTempFrame;
Misc.BindingOperations.SetBinding(mPDetect, nameof(mPDetect.FilmVelocity), mDynArea, nameof(mDynArea.FilmVelocity));
Misc.BindingOperations.SetBinding(this, nameof(NBolts), () =>
{
//TODO: 下面这些都没有用!!!!历史遗留问题
mDynArea.NBolts = NBolts;
mDynArea.FirstBoltNo = 1;
mDynArea.DataBoltNoBegin = 1;
mDynArea.DataBoltNoEnd = NBolts;
mDynArea.ScanBoltNoBegin = 1;
mDynArea.ScanBoltNoEnd = NBolts;
});
mProfileParam.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(mProfileParam.K))
{
//重新计算当前幅数据
UpdateCurrFrame();
}
};
mDynArea.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(mDynArea.SampleAD))
{
//重新计算当前幅数据
UpdateCurrFrame();
}
};
//记录调试数据
MarkDebugInit();
}
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 datOf1s = new List();//1秒数据缓存,用于求均值
void ClearDatOf1s() {
datOf1s_ts = TimeSpan.Zero;
datOf1s.Clear();
}
void flyad_TimeGridEvent(object sender, FlyADBase.TimeGridEventArgs e)
{
bool issample = false;
TimeSpan ts = e.Ts;//准确
//不使用AD盒的时间
//DateTime dt = e.Time;//准确
DateTime dt = DateTime.Now;//数据的尾
int[] data = e.Data;
//这个数据包的总耗时
TimeSpan data_interval = TimeSpan.FromTicks((long)(ts.TotalMilliseconds * data.Count() * TimeSpan.TicksPerMillisecond));
//这个数据包开始的时间
DateTime data_begin_dt = dt - data_interval;
//当前循环处理的数据
DateTime datOf100ms_dt = data_begin_dt - ts;
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;
datOf100ms_dt = datOf100ms_dt + ts;
if (datOf1s_ts >= datOf1s_interval)//1s 一个数据
{
int avgad = Misc.MyBase.NULL_VALUE;
if (datOf1s.Count() > 0)
{
avgad = Misc.MyMath.Avg(datOf1s);
}
else if (mADList.Count() > 0)
{
avgad = mADList.Last().Ad;
}
mADList.RAdd(
new ADCell()
{
Time = datOf100ms_dt,
Ad = avgad
});
ClearDatOf1s();
}
}
}
private void InitList()//初始化列表
{
if (mADList == null)
{
mADList = new RList(4000);
mADListToDoNo = mADList.GetLastNo();
mADListToDoNo_ToFilmInfo = mADListToDoNo;
}
if (mFrameInfoList == null)
mFrameInfoList = new RList(6);
}
//复位
void Clear()
{
if (mADList != null)
mADList.Clear();
if (mFrameInfoList != null)
{
mFrameInfoList.Clear();
}
ClearDatOf1s();
}
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
{
///
/// 时间点在列表以前;
///
Before = -1,
///
/// 时间点在列表中;
///
Now = 0,
///
/// 时间点在列表的未来;
///
Future = 1
}
///
/// 找到在 dt 前最近的 ADList 序号;
/// 当ADList 没有数据,返回 Future;
/// 已知AD列表每个数据之间的时间差,快速推断结果;
///
///
///
///
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);
//被测膜模式选择
switch (MMode)
{
case MeasureMode.Normal:
{
if (!OnPoll_UpdateADList_Normal(i))
return;
}
break;
default:
//case MeasureMode.Edge:
{
if (!OnPoll_UpdateADList_Edge(i))
return;
}
break;
}
}
mADListToDoNo = mADList.Index2No(mADList.Count);
}
#region 不同测量模式的ADList数据更新
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;
}
bool OnPoll_UpdateADList_Normal(int idx)
{
FilmInfo filminfo;
int ret = mPDetect.GetFilmInfo(out filminfo, mADList[idx].Time, FilmWidth, FilmPosH);
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.Angles.Add(filminfo.angle2);
adcell.Direction = filminfo.direction;
adcell.Velocity = filminfo.filmVelocity;
adcell.RotationCnt = filminfo.rotationCnt;
adcell.InCV = filminfo.inCV;
return true;
}
#endregion
///
/// 状态不一样,人字架已经转了新一圈,需要增加新一幅数据
///
///
///
///
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;
}
}
///
/// 输出的数据都必须是稳定,可靠的。 生成一幅幅测厚仪数据!!!!!!!!!!!!
///
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))
{
//一幅数据已经完成
switch (MMode)
{
case MeasureMode.Normal:
{
//最后检查一下是否需要解方程
frameinfo.SolveFormula();
}
break;
}
//重新分区
if (IsNeedMap())
{
//上面已经检查了 Map == null 的情况
Dictionary m = new Dictionary();
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 map;
if (IsNeedMap())
{
//上面已经检查了 Map == null 的情况
frame = frameinfo.frame_map;
map = new List();
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 = Math.Round(mPDetect.RAngle, 2),
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);
switch (MMode)
{
case MeasureMode.Normal:
{
//解方程,更新frameinfo.frame
var list = from a in adcell.Angles select Angle2BoltIndex(a);
frameinfo.SetFrameValue(list, thk * 2, adcell.Time);
}
break;
default:
//case MeasureMode.Edge:
{
//均值,更新frameinfo.frame
frameinfo.SetFrameValue(Angle2BoltIndex(adcell.Angles.First()), thk, adcell.Time);
}
break;
}
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];
switch (MMode)
{
case MeasureMode.Normal:
{
//最后检查一下是否需要解方程
frameinfo.SolveFormula();
}
break;
}
if (frameinfo.HasChanged)//数据检测过,需要更新bulkdata里面的数据, 大部分发生在扫描过程中,还没结束一幅图
{
//重新分区
if (IsNeedMap())
{
//上面已经检查了 Map == null 的情况
Dictionary m = new Dictionary();
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(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 bool Start()
{
//以前的 Start()
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));
return true;
}
#region sqlite3 历史数据保存
string[] profile_propertynames_add = new string[]{
"PName",
"OrderNo",
"Number"
};
string[] profile_propertynames_update = new string[]{
"Target",
"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 = "renzijiafix.json";
bool Load()
{
if (File.Exists(file_path))
{
try
{
string json = File.ReadAllText(file_path);
var jsonDb = JsonConvert.DeserializeObject(json);
BlowingFixJsonDb.Mapper.Map(jsonDb, this);
return true;
}
catch
{
//异常,没有json 解码失败
}
return false;
}
else//只是为了版本兼容,以后就会删除
{
var jsonDb = FLY.Thick.Blowing.Server.Update.GM_BlowingFix.ToJsonDb();
if (jsonDb == null)
return false;
BlowingFixJsonDb.Mapper.Map(jsonDb, this);
return true;
}
}
void Save()
{
try
{
var jsonDb = BlowingFixJsonDb.Mapper.Map(this);
string json = JsonConvert.SerializeObject(jsonDb, Formatting.Indented);
File.WriteAllText(file_path, json);
}
catch
{
//异常,没有json 编码失败
}
}
///
/// 获取 厚度列表
///
/// 开始时间
///
///
[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 BlowingFixJsonDb
{
public static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c => {
c.CreateMap().ReverseMap();
}));
public int ChannelCnt=88;
public int BPC=1;
public int OrgBoltNo=1;
public bool IsUsedMap;
public BoltMapCell[] Map;
public bool IsProbeRight = true;
}
}
namespace FLY.Thick.Blowing.Server.Update
{
public class GM_BlowingFix : ISaveToXml
{
///
/// 加热通道数
///
public int ChannelCnt { get; set; } = 88;
///
/// 分区数/加热通道数
///
public int BPC { get; set; } = 1;
///
/// 复位时,探头测量的位置对应分区号
///
public int OrgBoltNo { get; set; } = 1;
///
/// 使用分区表
///
public bool IsUsedMap { get; set; } = false;
///
/// 分区表,必须保证不能为null
///
public List Map { get; } = new List();
static GM_BlowingFix()
{
Misc.SaveToXmlHepler.Regist(typeof(BoltMapCell));
}
#region ISaveToXml
public string[] GetSavePropertyNames()
{
return new string[]{
nameof(ChannelCnt),
nameof(BPC),
nameof(OrgBoltNo),
nameof(IsUsedMap),
nameof(Map)
};
}
#endregion
public static BlowingFixJsonDb ToJsonDb()
{
if (File.Exists("renzijiafix.xml"))
{//只是为了版本兼容,以后就会删除
FLY.Thick.Blowing.Server.Update.GM_BlowingFix blowingFix = new Update.GM_BlowingFix();
Misc.SaveToXmlHepler.Load("renzijiafix.xml", blowingFix);
FLY.Thick.Blowing.Server.BlowingFixJsonDb jsonDb = new BlowingFixJsonDb();
jsonDb.ChannelCnt = blowingFix.ChannelCnt;
jsonDb.BPC = blowingFix.BPC;
jsonDb.OrgBoltNo = blowingFix.OrgBoltNo;
jsonDb.IsUsedMap = blowingFix.IsUsedMap;
jsonDb.Map = blowingFix.Map.ToArray();
return jsonDb ;
}
else
return null;
}
}
}