using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.IO;
using MathNet.Numerics.LinearAlgebra.Double;
using Misc;
using FLY.Thick.BulkDataModule;
using FlyADBase;
using FLY.Thick.Base.Common;
using FLY.Thick.BlowingScan.IService;
using FLY.Thick.Base.Server;
using FObjBase;
using FLY.Thick.BlowingScan.Common;
using FLY.Thick.Blowing.IService;
using FLY.Thick.Blowing.Server;
using FLY.Thick.Blowing.Server.Model;
using HistoryDb = FLY.Thick.BlowingScan.Server.Model.HistoryDb;
namespace FLY.Thick.BlowingScan.Server
{
public class GM_BlowingScan:GM_ScanMotion, IBlowingScanService,ISaveToXml
{
#region 延时操作,markno
const int MARKNO_SAVE = 1;
const int MARKNO_PROFILE_ADD = 87;
const int MARKNO_PROFILE_CHANGED = 88;
#endregion
///
///边界查找模块
///
private BorderSearch mBorderSearch;
///
///人字架位置检测器
///
public BlowingDetect mPDetect;
///
/// AD值转厚度值
///
private AD2ThickHandler AD2Thick;
///
/// 扫描数据库
///
private IBulkDataServiceAdd mBulkData;
BlowingProfileParam mProfileParam;
HistoryDb mHistoryDb;
BulkDb mBulkDb;
///
/// 上幅数据解方程失败,bookmark被释放出来
///
private int freebm=-1;
private int GetFreeBm()
{
int r = freebm;
freebm = -1;
return r;
}
private void SetFreeBm(int bm)
{
freebm = bm;
}
///
/// 动态数据组合
///
private DynArea mDynArea;
///
/// 扫描脉冲检测
///
private ScanPosDetect mScanPosDetect;
///
/// 当前扫描号
///
public int ScanNo =0;
class ScanPosCell
{
public DateTime dt = DateTime.MinValue;
public int pos;//位于膜的位置,不是机架
public int thick;//两层的厚度
//由pos转换!!
public double angle1;//上层 位于膜泡的角度
public double angle2;//下层 位于膜泡的角度
public Misc.DIRECTION direction;//只有一整副数据都是同一个方向,才能解方程
public ScanPosCell Clone()
{
ScanPosCell scanpos = new ScanPosCell();
scanpos.dt = dt;
scanpos.pos = pos;
scanpos.thick = thick;
scanpos.angle1 = angle1;
scanpos.angle2 = angle2;
scanpos.direction = direction;
return scanpos;
}
}
class EquationCell
{
public Dictionary boltPower=new Dictionary();//key=boltindex, value=power
public int thick=0;
public int mainBolt;//主分区号
public void Add(int boltindex1, int boltindex2, int thick)
{
if (boltPower.ContainsKey(boltindex1))
{
boltPower[boltindex1]++;
}
else
{
boltPower.Add(boltindex1, 1);
}
if (boltPower.ContainsKey(boltindex2))
{
boltPower[boltindex2]++;
}
else
{
boltPower.Add(boltindex2, 1);
}
this.thick += thick;
}
public override string ToString()
{
string str = "";
foreach (var b in boltPower)
{
str += "[" + b.Key.ToString() + "," + b.Value.ToString() + "] ";
}
return str;
}
public double[] GetPower(int nbolts)
{
double[] power = new double[nbolts];
for (int i = 0; i < power.Count(); i++)
power[i] = 0;
foreach (var kv in boltPower)
{
power[kv.Key] = kv.Value;
}
return power;
}
public int GetAvg()
{
int cnt=0;
for (int i = 0; i < boltPower.Count(); i++)
{
cnt += boltPower.Values.ElementAt(i);
}
if (cnt > 0)
return thick / cnt;
else
return Misc.MyBase.NULL_VALUE;
}
}
class ScanInfoCell
{
public ScanInfoCell Clone()
{
ScanInfoCell scaninfo = new ScanInfoCell(ScanNo, thicks.Count());
scaninfo.Direction = Direction;
scaninfo.ScanNo = ScanNo;
scaninfo.IsFull = IsFull;
scaninfo.IndexOfToGetTime = IndexOfToGetTime;
foreach(ScanPosCell scanpos in frame)
{
scaninfo.frame.Add(scanpos.Clone());
}
scaninfo.width = width;
scaninfo.beginPos = beginPos;
scaninfo.endPos = endPos;
scaninfo.lockbm = lockbm;
return scaninfo;
}
public enum GetAngleResult
{
///
/// 全部grid 数据已经获取,而且都成功转为方程
///
AllGet,
///
/// 部分grid 数据已经获取,这次转化了一些方程
///
PartGet,
///
/// 什么都没干,没有转化为任何方程
///
NothingToDo
}
public GetAngleResult GetAngle(BlowingDetect rdetect, int orgboltno, int sensorWidth)
{
bool bHasNewData = false;
for (; IndexOfToGetAngle < IndexOfToGetTime; IndexOfToGetAngle++)
{
int i = IndexOfToGetAngle;
ScanPosCell scanpos = frame[i];
BlowingDetect.FilmInfo filminfo;
if (scanpos.dt == DateTime.MinValue)
{
}
int ret = rdetect.GetFilmInfo(
out filminfo,
scanpos.dt,
width,
scanpos.pos
);
if (ret == 1)
{
//发生在未来,等下一次Poll
if (IsFull)
return GetAngleResult.NothingToDo;
else
{
if (bHasNewData)
return GetAngleResult.PartGet;
else
return GetAngleResult.NothingToDo;
}
}
//成功获取
scanpos.angle1 = filminfo.angle1;
scanpos.angle2 = filminfo.angle2;
scanpos.direction = filminfo.direction;
if (IndexOfToGetAngle == 0)
{
Direction = scanpos.direction;
}
else
{
if (Direction != scanpos.direction)
{
Direction = DIRECTION.FIX;
}
}
//探头直径转为角度范围
double sensor_angle = 180.0 * sensorWidth / width;
if (AddEquation(i, orgboltno, sensor_angle))
bHasNewData = true;
}
if (IsFull)
return GetAngleResult.AllGet;
else
{
if (bHasNewData)
return GetAngleResult.PartGet;
else
return GetAngleResult.NothingToDo;
}
}
int GetBoltIndexFromAngle(double a, int orgboltno)
{
int boltno1st = 1;
int nbolts = thicks.Count();
int boltindex = (int)(a / 360 * nbolts);
boltindex += orgboltno - boltno1st;
if (boltindex >= nbolts)
boltindex -= nbolts;
return boltindex;
}
int boltindex1_last = -1;
///
/// 完成了一些方程,返回true
///
///
/// 复位区号
/// 探头直径对应的角度范围
///
bool AddEquation(int scanpos_idx, int orgboltno, double sensor_angle)
{
ScanPosCell scanpos = frame[scanpos_idx];
if (equationList.Count() == 0)//复位记录
boltindex1_last = -1;
EquationCell equation = new EquationCell();
equationList.Add(equation);
int boltindex1 = GetBoltIndexFromAngle(scanpos.angle1, orgboltno);
equation.mainBolt = boltindex1;
equation.Add(
GetBoltIndexFromAngle(scanpos.angle1, orgboltno),
GetBoltIndexFromAngle(scanpos.angle2, orgboltno),
scanpos.thick);
//添加直径范围内的方程
for (int i = 1; i < sensor_angle / 2; i++)
{
equation.Add(
GetBoltIndexFromAngle(scanpos.angle1 + i, orgboltno),
GetBoltIndexFromAngle(scanpos.angle2 + i, orgboltno),
scanpos.thick);
equation.Add(
GetBoltIndexFromAngle(scanpos.angle1 - i, orgboltno),
GetBoltIndexFromAngle(scanpos.angle2 - i, orgboltno),
scanpos.thick);
}
if (boltindex1_last != boltindex1)//记录不同,通知外部是时候解方程了
{
boltindex1_last = boltindex1;
return true;
}
return false;
}
public int GetAvg()
{
if (equationList.Count() < 0)
return Misc.MyBase.NULL_VALUE;
int sum = 0;
int cnt = 0;
for (int i = 0; i < equationList.Count(); i++)
{
EquationCell equation = equationList[i];
int a = equation.GetAvg();
if (Misc.MyBase.ISVALIDATA(a))
{
sum += a;
cnt++;
}
}
if (cnt > 0)
return sum / cnt;
else
return Misc.MyBase.NULL_VALUE;
}
//public void SaveEquation(StreamWriter sw)
//{
// for (int i = 0; i < equationList.Count(); i++)
// {
// EquationCell equation = equationList[i];
// string s = ScanNo.ToString();
// s +=","+ Direction.ToString();
// s += "," + StartTime.ToString();
// s+=","+equation.thick.ToString();
// for (int j = 0; j < equation.boltPower.Count(); j++)
// {
// int boltindex = equation.boltPower.Keys.ElementAt(j);
// s += "," + boltindex.ToString();
// s += "," + equation.boltPower[boltindex].ToString();
// }
// sw.WriteLine(s);
// }
//}
//public static void SaveEquation_Header(StreamWriter sw)
//{
// string s = "序号,方向,时间,总厚度,序号1,数量1,序号2,数量2";
// sw.WriteLine(s);
//}
public ScanInfoCell(int scanNo, int nbolts)
{
Reset(scanNo);
thicks = new int[nbolts];
for (int i = 0; i < nbolts; i++)
{
thicks[i] = Misc.MyBase.NULL_VALUE;
}
}
///
/// 开始测量时间
///
public DateTime StartTime;
///
/// 结束测量时间
///
public DateTime EndTime;
///
/// 旋转架旋转的方向,当同一次扫描中,有两个方向,Direction= Fix;
///
public Misc.DIRECTION Direction;
///
/// 扫描号,必须唯一!!!!!
///
public int ScanNo;
///
/// grid数据,已经全部放入!!!!!
///
public bool IsFull;
///
/// 准备要去获取时间的ScanPosCell序号, -1, 整个scaninfo 都发生在过去,作废
///
public int IndexOfToGetTime;
///
/// 准备要去转角度的ScanPosCell序号
///
public int IndexOfToGetAngle;
///
/// 快速解方法,equationList序号
///
public int IndexOfToSolveEquationQuick;
public void Reset(int scanNo)
{
ScanNo = scanNo;
frame.Clear();
equationList.Clear();
IsFull = false;
IndexOfToGetTime = 0;
IndexOfToGetAngle = 0;
Direction = DIRECTION.FORWARD;
}
///
/// 复位数据;一幅grid成功生成,重新获取pos,thick,time,angle,equation
///
///
///
public void Reset_IsFull(int beginPos, int endPos)
{
this.beginPos = beginPos;
this.endPos = endPos;
this.width = endPos - beginPos + 1;//膜宽
this.IsFull = true;
equationList.Clear();
frame.Clear();
IndexOfToGetTime = 0;
IndexOfToGetAngle = 0;
}
void ClearFrame()
{
equationList.Clear();
frame.Clear();
IndexOfToGetTime = 0;
IndexOfToGetAngle = 0;
}
public void Reset2GetAngle()
{
IndexOfToGetAngle = 0;
equationList.Clear();
for (int i = 0; i < thicks.Count(); i++)
thicks[i] = Misc.MyBase.NULL_VALUE;
}
///
/// 原始数据(时间,位置,总厚度
///
public List frame=new List();
///
/// 膜的宽度
///
public int width=-1;
///
/// 膜边界左
///
public int beginPos;
///
/// 膜边界右
///
public int endPos;
///
/// 方程列表
///
public List equationList=new List();
///
/// 下面解方程得到的一幅数据对应的数据,与 StartTime 不一样
///
public DateTime thicks_dt;
///
/// 一幅数据
///
public int[] thicks;
///
/// 经过分区表后的结果
///
public int[] thicks_map;
///
/// 对应bulkdata 的数据, -1, 没有对应的bookmark,因为从来都没数据
///
public int bookmark=-1;
///
/// 锁定 bookmark,只要解过一次方程,bookmark 就会被锁定,不能再修改
///
public bool lockbm = false;
public class SolveQuickResult
{
///
/// 新得到数据开始序号
///
public int start_index;
///
/// 新得到数据长度,这是一个环形队列
///
public int len=0;
}
///
/// 快速解方程
///
/// 上一幅完成的数据
/// 上一幅图所占的权重,当前只占1
///
public SolveQuickResult SolveQuick(int[] org_thicks, int power)
{
List updateboltindex = new List();
for (int i = IndexOfToSolveEquationQuick; i < equationList.Count; i++, IndexOfToSolveEquationQuick++)
{
EquationCell equation = equationList[i];
int mainpower = equation.boltPower[equation.mainBolt];
double sum = 0;
for (int j = 0; j < equation.boltPower.Count; j++)
{
int boltindex = equation.boltPower.Keys.ElementAt(j);
if (boltindex != equation.mainBolt)
{
if (org_thicks == null)
{
mainpower += equation.boltPower[boltindex];
}
else if (!Misc.MyBase.ISVALIDATA(org_thicks[boltindex]))
{
mainpower += equation.boltPower[boltindex];
}
else
{
sum += equation.boltPower[boltindex] * org_thicks[boltindex];
}
}
}
int mainBolt_value = (org_thicks != null)? org_thicks[equation.mainBolt]:Misc.MyBase.NULL_VALUE;
if (Misc.MyBase.ISVALIDATA(mainBolt_value))
{
thicks[equation.mainBolt] = (mainBolt_value * power + (int)((equation.thick - sum) / mainpower)) / (power + 1);
}
else
{
thicks[equation.mainBolt] = (int)((equation.thick - sum) / mainpower);
}
updateboltindex.Add(equation.mainBolt);
}
SolveQuickResult result = new SolveQuickResult();
if (updateboltindex.Count > 0)
{
result.start_index = updateboltindex.Min();
result.len = updateboltindex.Max() - updateboltindex.Min() + 1;
}
return result;
}
}
///
/// 每次扫描的数据,
/// 不是每一幅数据都能解出方程,
/// 因为要连续3幅才能解出方程
///
private RList mScanInfoList;
///
/// 与 mScanInfoList 基本一样
///
private RList mBufList;
#region ISaveToXml
public string[] GetSavePropertyNames()
{
return new string[]{
"ChannelCnt",
"BPC",
"OrgBoltNo",
"SolveCnt",
"Smooth",
"SensorWidth",
"IsUsedMap",
"Map"
};
}
#endregion
#region IRenZiJiaService
#region 分区设置
///
/// 加热通道数
///
public int ChannelCnt { get; set; } = 88;
///
/// 分区数/加热通道数
///
public int BPC { get; set; } = 1;
///
/// 风环螺丝数
///
public int NBolts => ChannelCnt * BPC;
///
/// 人字架复位时,对应的螺丝号,0° 对应的 螺丝号
///
public int OrgBoltNo { get; set; } = 1;
private int smooth = 1;
///
/// 平滑
///
public int Smooth
{
get { return smooth; }
set
{
if (value < 0)
value = 0;
if (smooth != value)
{
smooth = value;
}
}
}
///
/// 使用分区表
///
public bool IsUsedMap { get; set; }
bool IsNeedMap()
{
if (IsUsedMap && Map.Count() > 0)
return true;
else
return false;
}
private List map = new List();
///
/// 分区表,必须保证不能为null
///
public List Map
{
get { return map; }
set
{
//检测是否不一样
if (value == null)
return;
if (checkNoSame_map(map, value))
{
if (!checkParamErr_map(value))
{
IsUsedMap = false;
map = new List();
}
else
{
map = value;
}
}
}
}
bool checkNoSame_map(List mapCells1, List mapCells2)
{
if (mapCells1.Count() != mapCells2.Count())
return true;
for (int i = 0; i < mapCells1.Count(); i++)
{
var mapCell1 = mapCells1[i];
var mapCell2 = mapCells2[i];
if (mapCell1.NewNo != mapCell2.NewNo)
return true;
if (mapCell1.OldNo != mapCell2.OldNo)
return true;
}
return false;
}
///
/// 检测通过,返回true
///
///
bool checkParamErr_map(List mapCells)
{
bool map_err = false;
bool g_o = false;
bool g_n = false;
//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;
}
}
#endregion
///
/// 应用
///
public void Apply()
{
Save();
}
///
/// 扫描一次推送事件
///
public event RenZiJiaDataEventHandler DataEvent;
#endregion
///
/// 缓冲区第一个记录序号
///
public int FirstBM { get; set; } = -1;
///
/// 缓冲区最后一个记录序号
///
public int LastBM { get; protected set; } = -1;
private int sensorwidth = 250;
///
/// 探头宽度,用于解方程,可以与实际不符合 单位脉冲
///
public int SensorWidth
{
get { return sensorwidth; }
set
{
if (value < 1)
value = 1;
if (sensorwidth != value)
{
sensorwidth = value;
}
}
}
private int solvecnt = 4;
///
/// 多少次扫描解一次方程
///
public int SolveCnt
{
get { return solvecnt; }
set
{
if (value < 3)
value = 3;
if (solvecnt != value)
{
solvecnt = value;
}
}
}
void checkParamErr()
{
if (ChannelCnt < 20 || ChannelCnt > 160)
{
ChannelCnt = 44;
}
if (BPC < 1 || BPC > 4)
{
BPC = 2;
}
if (OrgBoltNo < 1 || OrgBoltNo > NBolts)
{
OrgBoltNo = 1;
}
if (SolveCnt > 20)
{
SolveCnt = 5;
}
if (!checkParamErr_map(Map))
{
IsUsedMap = false;
Map = new List();
}
}
static GM_BlowingScan()
{
Misc.SaveToXmlHepler.Regist(typeof(BoltMapCell));
}
///
///
///
///
///
public GM_BlowingScan(FlyAD7 flyad, GSample gsample)
: base(flyad, gsample)
{
mPDetect = new BlowingDetect();
mScanInfoList = new RList(30);
mBufList = new RList(100);
mScanPosDetect = new ScanPosDetect();
ChannelCnt = 44;//加热棒数量
BPC = 2;//分区数量/加热棒数量
OrgBoltNo = 10;//复位时,测厚仪对应的螺丝号
SolveCnt = 5;
mPDetect.Load();
Load();
//检测参数
mPDetect.CheckParamErr();
checkParamErr();
if (SolveCnt < 3)
SolveCnt = 3;
PropertyChanged+=new PropertyChangedEventHandler(RenZiJiaScan_PropertyChanged);
mPDetect.PropertyChanged += (s, e) =>
{
NotifyPropertyChanged(e.PropertyName);
};
mPDetect.FilmInfoChangedEvent += new BlowingDetect.FilmInfoChangedEventHandler(mPDetect_FilmInfoChangedEvent);
mPDetect.ClearEvent += new BlowingDetect.ClearEventHandler(mPDetect_ClearEvent);
mPDetect.Init(mFlyAD);
mScanPosDetect.Init(mFlyAD);
ScanCnt = -1;
}
bool Load()
{
return Misc.SaveToXmlHepler.Load("renzijiascan.xml", this);
}
void Save()
{
Misc.SaveToXmlHepler.Save("renzijiascan.xml", this);
}
///
///
///
///
///
///
///
///
///
///
public void Init(
IBulkDataServiceAdd bulkdata,
BorderSearch borderSearch,
DynArea dynArea,
AD2ThickHandler func_ad2thick,
BlowingProfileParam profileParam,
HistoryDb historyDb, BulkDb bulkDb
)
{
AD2Thick = func_ad2thick;
mBulkData = bulkdata;
mBorderSearch = borderSearch;
mDynArea = dynArea;
mProfileParam = profileParam;
mHistoryDb = historyDb;
mBulkDb = bulkDb;
//接收PollScan的推送
DataPosEvent += new EndEventHandler(pollScan_DataPosEvent);
EndEvent += new EndEventHandler(pollScan_EndEvent);
//记录调试数据
MarkDebugInit();
}
#region 记录原始数据
DateTime markdebug_dt = DateTime.MinValue;
int markdebug_lastBm = -1;
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, (asyncState, retData) =>
{
var reponse = retData as GetSignListReponse;
var cells = reponse.datas;
if (cells.Count > 0)
{
mHistoryDb.AddSignData(
new Lc_Sign()
{
Time = cells.First().Time,
Signs = cells.ToArray()
});
}
}, null);
mPDetect.GetRollList(markdebug_dt, (asyncState, retData) =>
{
var reponse = retData as GetRollListReponse;
var cells = reponse.datas;
if (cells.Count > 0)
{
mHistoryDb.AddRollData(
new Lc_Roll()
{
Time = cells.First().dt,
Signs = cells.ToArray()
});
}
}, null);
this.GetBufList((asyncState, retData) =>
{
var reponse = retData as GetBufListReponse;
var cells = reponse.datas;
if (cells.Count() == 0)
{
//没有数据
markdebug_lastBm = reponse.lastbm;
return;
}
int new_cnt = reponse.lastbm - markdebug_lastBm;
if (new_cnt > cells.Count())
new_cnt = cells.Count();
markdebug_lastBm = reponse.lastbm;
if (new_cnt <= 0)
return;
List lc_OrgScanDatas = new List();
for (int i = 0; i < new_cnt; i++)
{
int index = reponse.datas.Count() - new_cnt + i;
var data = reponse.datas[index];
var times = data.ThicksDt.Where(dt => dt != DateTime.MinValue);
if (times.Count() == 0)
continue;
Model.Lc_OrgScanData lcOrgScanData = new Model.Lc_OrgScanData();
lcOrgScanData.Time = times.Min();
lcOrgScanData.FilmBegin = data.FilmRange.Begin;
lcOrgScanData.FilmEnd = data.FilmRange.End;
lcOrgScanData.PosOfGrid = data.PosOfGrid;
lcOrgScanData.K = mProfileParam.K;
lcOrgScanData.Thicks = ToRealThicks(data.Thicks);
lcOrgScanData.ThicksDt = data.ThicksDt;
lc_OrgScanDatas.Add(lcOrgScanData);
}
mHistoryDb.AddOrgScanDatas(lc_OrgScanDatas);
}, null);
markdebug_dt = DateTime.Now;
},
TimeSpan.FromMinutes(1));
}
#endregion
double[] ToRealThicks(IEnumerable frame)
{
return frame.Select(t =>
{
if (Misc.MyBase.ISVALIDATA(t))
return t / 100.0;
else
return double.NaN;
}).ToArray();
}
void RenZiJiaScan_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "NBolts")
{
//所有数据删除
mScanInfoList.Clear();
//TODO!!!!!
//停下来
}
}
void mPDetect_FilmInfoChangedEvent(object sender, BlowingDetect.FilmInfoChangedEventArgs e)
{
// 找到 e.Time 对应的 scaninfo
for (int i = 0; i < mScanInfoList.Count; i++)
{
ScanInfoCell scaninfo = mScanInfoList[i];
if (scaninfo.IndexOfToGetTime > 0)
{
DateTime dt_start = scaninfo.frame[0].dt;
DateTime dt_end = scaninfo.frame[scaninfo.IndexOfToGetTime-1].dt;
if (e.Time < dt_end)//找到了
{
for (int j = i; j < mScanInfoList.Count; j++)
{
scaninfo = mScanInfoList[j];
scaninfo.IndexOfToGetAngle = 0;
}
return;
}
}
}
}
void mPDetect_ClearEvent(object sender)
{
//已经很久没数据,清空全部!!!!!!!
//scanposdetect
mScanPosDetect.ScanNo = ScanNo;
if (mScanInfoList.Count > 0)
{
mScanInfoList.Clear();
//scaninfo
ScanInfoCell scaninfo = new ScanInfoCell(ScanNo, NBolts);
//scaninfo.bookmark = bookmark;
mScanInfoList.Add(scaninfo);
}
}
#region 1.grid 数据 转 ScanPosCell.(pos,thick) 放入 mScanInfoList.Last()
///
/// 动态获取!!!!
///
///
///
void pollScan_DataPosEvent(object obj, FlyADBase.MiniGridEventArgs e)
{
DIRECTION direction = e.direction;
int posOfGrid = e.posOfGrid;
int start_idx = e.grid_start;
int start_pos = e.grid_start * e.posOfGrid;
int[] dat = e.buf;
//-------------------------------------
//DIR
mDynArea.Direction = direction;
mDynArea.AD = dat[0];
mDynArea.Thick = AD2Thick(dat[0]);
if (mScanInfoList.Count == 0)
return;
ScanInfoCell scaninfocell = mScanInfoList.Last();
if (scaninfocell.width <= 0)
{
//刚开始,连膜边都还没找到
return;
}
//找边界前,要对数据进行校正
//尽可能不要两个边的数据,N2是边界向内减, 只是不要更多的数据而已
int bp = scaninfocell.beginPos + mBorderSearch.N2;
int ep = scaninfocell.endPos - mBorderSearch.N2;
//对应的grid号
int bp_idx = bp / posOfGrid;
int ep_idx = ep / posOfGrid;
if(bp_idx < start_idx)
bp_idx = start_idx;
if(ep_idx > (start_idx+dat.Length-1))
ep_idx = start_idx+dat.Length-1;
for (int i = bp_idx; i <= ep_idx; i++)
{
int idx = i - start_idx;
int pos = i * posOfGrid + posOfGrid / 2;//一个grid的中间脉冲,也就是大概而已
int thick = Misc.MyBase.NULL_VALUE;
if (Misc.MyBase.ISVALIDATA(dat[idx]))
thick = AD2Thick(dat[idx])*2;
pos -= scaninfocell.beginPos;//膜上面的位置
scaninfocell.frame.Add(new ScanPosCell() { pos = pos, thick = thick });
}
OnPoll_GetTime2();
}
void pollScan_EndEvent(object obj, FlyADBase.MiniGridEventArgs e)
{
DIRECTION direction = e.direction;
int posOfGrid = e.posOfGrid;
int start_idx = e.grid_start;
int start_pos = e.grid_start * e.posOfGrid;
int[] dat = e.buf;
//int scaninfo_idx = mScanInfoList.FindIndex(sil => sil.IndexOfToGetTime < sil.frame.Count);
//if ((scaninfo_idx>0) && (mScanInfoList.Count - scaninfo_idx > 1) )
//{
// //有问题
//}
ScanNo++;
mScanPosDetect.ScanNo = ScanNo;
if(gsample.Samples[0].AD <= 0)
{
//无温修AD
if (mScanInfoList.Count == 0)
return;
ScanInfoCell scaninfo = mScanInfoList.Last();
if (scaninfo.bookmark != -1)
mBulkData.ChangeEmply(scaninfo.bookmark);
scaninfo.Reset(ScanNo);
return;
}
//找边界
bool ret = mBorderSearch.FindFilm(direction, posOfGrid, start_idx, dat);
if (!ret)//不能找到边界!!!没膜!!!!
{
mBorderSearch.Init();
}
//设置扫描范围
//POLLSCAN----------------------------------------
Range scanrange = mBorderSearch.GetScanRange();
ScanStart = scanrange.Begin;// beginPos;
ScanEnd = scanrange.End;// endPos;
if (!ret)
{
if (mScanInfoList.Count == 0)
return;
ScanInfoCell scaninfo = mScanInfoList.Last();
if (scaninfo.bookmark != -1)
mBulkData.ChangeEmply(scaninfo.bookmark);
scaninfo.Reset(ScanNo);
return;
}
//必须设置好 mBorderSearch.SensorWidth,它就是探头直径
Range border = mBorderSearch.GetBorder(direction);
if (mScanInfoList.Count == 0)//安全检查,不可能发生的!!!!!
return;
ScanInfoCell scaninfocell = mScanInfoList.Last();
//膜宽,和位置一起计算旋转架上的角度
scaninfocell.Reset_IsFull(border.Begin, border.End);
//尽可能不要两个边的数据,N2是边界向内减, 只是不要更多的数据而已
Range boltrange = mBorderSearch.GetBoltRange(direction);
//对应的grid号
int bp_idx = boltrange.Begin / posOfGrid;
int ep_idx = boltrange.End / posOfGrid;
if (bp_idx < start_idx)
bp_idx = start_idx;
if (ep_idx > (start_idx + dat.Length - 1))
ep_idx = start_idx + dat.Length - 1;
for (int i = bp_idx; i <= ep_idx; i++)
{
int idx = i - start_idx;
int pos = i * posOfGrid + posOfGrid / 2;//一个grid的中间脉冲,也就是大概而已
int thick = Misc.MyBase.NULL_VALUE;
if (Misc.MyBase.ISVALIDATA(dat[idx]))
thick = AD2Thick(dat[idx]) * 2;
pos -= border.Begin;//膜上面的位置
scaninfocell.frame.Add(new ScanPosCell() { pos = pos, thick = thick });
}
//或取每个数据对应的时间点
OnPoll_GetTime2();
//把扫描数据放多一份到 mBufList
PushToBufList(e, border, scaninfocell.ScanNo);
//插入纵向数据
#region sqlite3 历史数据保存
{
List boltValues = new List();
double boltwidth = scaninfocell.width * 1.0 / (NBolts / 2);
int boltIdx = 0;
double boltSum = 0;
int boltCnt = 0;
for (int i = 0; i < scaninfocell.frame.Count(); i++)
{
int idx = (int)(scaninfocell.frame[i].pos / boltwidth);
if (boltIdx != idx)
{
if (boltCnt > 0)
{
boltValues.Add(boltSum / boltCnt);
boltSum = 0;
boltCnt = 0;
}
}
boltIdx = idx;
if (Misc.MyBase.ISVALIDATA(scaninfocell.frame[i].thick))
{
boltSum += scaninfocell.frame[i].thick / 2 / 100.0;
boltCnt++;
}
}
if (boltCnt > 0)
{
boltValues.Add(boltSum / boltCnt);
boltSum = 0;
boltCnt = 0;
}
mHistoryDb.AddTrendData(new Lc_TrendData()
{
Time = DateTime.Now,
K = mProfileParam.K,
Thicks = boltValues.ToArray()
});
}
#endregion
//创建一个新的 scaninfocell
//为下一趟即时扫描作准备
scaninfocell = new ScanInfoCell(ScanNo,NBolts);
direction = (direction == DIRECTION.FORWARD) ? DIRECTION.BACKWARD : DIRECTION.FORWARD;
border = mBorderSearch.GetBorder(direction);
scaninfocell.beginPos = border.Begin;
scaninfocell.endPos = border.End;
scaninfocell.width = border.Width;//膜宽
scaninfocell.IsFull = false;
mScanInfoList.RAdd(scaninfocell);
}
void PushToBufList(MiniGridEventArgs e, Range border, int scanNo)
{
DIRECTION direction = e.direction;
int posOfGrid = e.posOfGrid;
int start_idx = e.grid_start;
int start_pos = e.grid_start * e.posOfGrid;
int[] dat = e.buf;
FlyData_BlowingScan f = new FlyData_BlowingScan();
f.FilmRange = border;
f.PosOfGrid = posOfGrid;
f.Thicks = new int[mFlyAD.PosLen/ posOfGrid];
f.ThicksDt = new DateTime[f.Thicks.Count()];
//对应的grid号
for (int i = 0; i < f.Thicks.Count(); i++)
{
int idx = i - start_idx;
int pos = i * posOfGrid + posOfGrid / 2;//一个grid的中间脉冲,也就是大概而已
int thick = Misc.MyBase.NULL_VALUE;
if (idx >= 0 && idx < dat.Count())
{
if (Misc.MyBase.ISVALIDATA(dat[idx]))
thick = AD2Thick(dat[idx]) * 2;
}
f.Thicks[i] = thick;
DateTime dt = DateTime.MinValue;
if (Misc.MyBase.ISVALIDATA(thick))
{
int ret = mScanPosDetect.GetTime(pos, scanNo, out dt);
}
f.ThicksDt[i] = dt;
}
f.RotateCnt = mPDetect.RotationCnt;
if (mPDetect.mLimitList.Count() > 0)
{
LimitCell lc = mPDetect.mLimitList.Last();
f.SignNo = lc.no;
f.Time = lc.dt_begin;
f.LeaveTime = lc.dt_end;
}
else
{
f.SignNo = -1;
f.Time = DateTime.MinValue;
f.LeaveTime = DateTime.MinValue;
}
f.LimitSignTime = mPDetect.LimitSignTime;
f.RotatePeriod = mPDetect.RenZiJiaPeriod;
f.Velocity = mPDetect.FilmVelocity;
mBufList.RAdd(f);
FirstBM = mBufList.Index2No(0);
LastBM = mBufList.GetLastNo();
}
#endregion
#region 2.填入 ScanPosCell.(dt)
///
/// 找到一幅数据,每个grid 对应的时间点
///
void OnPoll_GetTime2()
{
ScanInfoCell scaninfo = mScanInfoList.Last();
for (; scaninfo.IndexOfToGetTime < scaninfo.frame.Count; scaninfo.IndexOfToGetTime++)
{
int i = scaninfo.IndexOfToGetTime;
ScanPosCell scanpos = scaninfo.frame[i];
//还原为机架位置
int pos = scaninfo.beginPos + scanpos.pos;
DateTime dt;
int ret = mScanPosDetect.GetTime(pos, scaninfo.ScanNo, out dt);
if (ret == -2)
{
//发生在过去,不正常
}
else if (ret == 1)//这个是未来的,等下一次Poll
{
return;
}
else if (dt == DateTime.MinValue)
{
//出错, 把scaninfo 删除掉
//mScanInfoList.RemoveAt(scaninfo_idx);
//scaninfo_idx--;
break;
}
//成功获取
scanpos.dt = dt;
if (i == 0)
{
scaninfo.StartTime = dt;
scaninfo.thicks_dt = dt;
}
scaninfo.EndTime = dt;
}
}
#endregion
#region 3.填入 ScanPosCell.(angle1,angle2), 且转为 Equation
void OnPoll_GetAngle()
{
int scaninfo_idx = mScanInfoList.FindIndex(
sil =>
(sil.IndexOfToGetAngle < sil.IndexOfToGetTime));
if (scaninfo_idx == -1)
{
return;//全部都转换完成!!
}
while (true)
{
ScanInfoCell scaninfo = mScanInfoList[scaninfo_idx];
ScanInfoCell.GetAngleResult result = scaninfo.GetAngle(mPDetect, OrgBoltNo, SensorWidth);
if (result == ScanInfoCell.GetAngleResult.NothingToDo)
{
//getangle 失败,发生在未来,等下一次Poll
break;
}
//解方程,画数据!!
ToThicks(scaninfo_idx);
//全部GetAngle 成功,下一个scaninfo
scaninfo_idx++;
if (scaninfo_idx >= mScanInfoList.Count)
break;//已经没有了
}
}
class CalSolveCnt
{
List list = new List();
const int listcap = 5;
void Add(int cnt)
{
list.Add(cnt);
if (list.Count > listcap)
list.RemoveAt(0);
}
public int Max()
{
if (list.Count > 0)
return list.Max();
else
return 4;
}
Misc.DIRECTION direction = DIRECTION.FIX;
int cnt = 0;
public bool Check(Misc.DIRECTION direction)
{
if (this.direction != direction)
{
if((this.direction!=Misc.DIRECTION.FIX) && (cnt>3))
Add(cnt);
cnt = 0;
}
cnt++;
this.direction = direction;
return OK();
}
public bool OK()
{
if (list.Count >= listcap)
{
return true;
}
return false;
}
}
CalSolveCnt mCalSolveCnt = new CalSolveCnt();
bool ToThicks_SolveEquation(int scaninfo_idx)
{
ScanInfoCell scaninfo = mScanInfoList[scaninfo_idx];
if (scaninfo.Direction == DIRECTION.FIX)//当前是Fix 不解方程
return false;
//解方程数量检测,免得一直数量不足,解不了方程
//if (mCalSolveCnt.Check(scaninfo.Direction))
//{
// if (SolveCnt > (mCalSolveCnt.Max()-1))
// {
// SolveCnt = (mCalSolveCnt.Max() - 1);
// }
//}
if (scaninfo_idx < (SolveCnt - 1))
return false;
//全部方向都必须一致,当然也不能是Fix
//for (int i = 0; i < (SolveCnt - 1); i++)
//{
// if (scaninfo.Direction != mScanInfoList[scaninfo_idx - 1 - i].Direction)
// return false;
//}
int avg = scaninfo.GetAvg();
if (!Misc.MyBase.ISVALIDATA(avg))//平均值不合法!!!!
return false;
if (avg < 500)//值太小!!!
return false;
List equationlist = new List();
////全部平均值相差不能超过 5%
//for (int i = 0; i < SolveCnt; i++)
//{
// int a = mScanInfoList[scaninfo_idx - 1 - i].GetAvg();
// if (Math.Abs((a - avg) / avg) > 0.05)
// return false;
// equationlist.AddRange(mScanInfoList[scaninfo_idx - i].equationList);
//}
int cnt = 0;
for (int i = scaninfo_idx; i >=0; i--)
{
if (mScanInfoList[i].Direction == DIRECTION.FIX)
continue;
cnt++;
double a = mScanInfoList[i].GetAvg();
double p = (a - avg) / avg;
if (Math.Abs(p) > 0.05)
return false;
equationlist.AddRange(mScanInfoList[i].equationList);
if (cnt >= SolveCnt)
break;
}
if (cnt < SolveCnt)//方程不够!!!!
return false;
if (equationlist.Count < 100)//方程数太少
return false;
//2105 条方程,耗时 0.3s
SolveEquation(mScanInfoList[scaninfo_idx].thicks, equationlist);
//不能有任何一个NULL_VALUE
for (int i = 0; i < scaninfo.thicks.Count(); i++)
{
if (scaninfo.thicks[i] > 1000000)
return false;
if (scaninfo.thicks[i] < -10000)
return false;
}
//检测
{
int sigma = Misc.MyMath.Sigma(scaninfo.thicks);
int avg2 = Misc.MyMath.Avg(scaninfo.thicks);
double p = 1.0 * (avg2 - avg) / avg;
if (Math.Abs(p) > 0.05)//变化太大,不可能!!!
return false;
p = 1.0 * sigma / avg2;
if (Math.Abs(p) > 0.5) //波动太大,异常
return false;
}
//最后处理,滤波,平滑
if (Smooth > 0)
{
int[] data = new int[scaninfo.thicks.Count()];
for (int i = 0; i < scaninfo.thicks.Count(); i++)
{
int sum = 0;
for (int j = 0; j < (Smooth * 2 + 1); j++)
{
int index = i + j - Smooth;
if (index < 0)
index += scaninfo.thicks.Count();
else if (index >= scaninfo.thicks.Count())
index -= scaninfo.thicks.Count();
sum += scaninfo.thicks[index];
}
data[i] = (int)(sum / (Smooth * 2 + 1));
}
Array.Copy(data, scaninfo.thicks, data.Count());
}
scaninfo.thicks_dt = mScanInfoList[scaninfo_idx - (SolveCnt-1)].StartTime;
return true;
}
enum BindingMotion
{
Add,
Remove
}
void BookmarkRestartToBinding(int scaninfo_idx, BindingMotion motion)
{
if (motion == BindingMotion.Add)
{
if (mScanInfoList[scaninfo_idx].bookmark == -1)
{
int bookmark = mScanInfoList[scaninfo_idx].bookmark;
mBulkData.ChangeEmply(bookmark);
//删除与 bulkdata 关系
mScanInfoList[scaninfo_idx].bookmark = -1;
for (int i = mScanInfoList.Count()-1;i>(scaninfo_idx + 1); i--)
{
if (mScanInfoList[i].bookmark != -1)
{
int tmp = bookmark;
bookmark = mScanInfoList[i].bookmark;
mScanInfoList[i].bookmark = tmp;
}
}
}
}
else
{
if (mScanInfoList[scaninfo_idx].bookmark != -1)
{
int bookmark = mScanInfoList[scaninfo_idx].bookmark;
mBulkData.ChangeEmply(bookmark);
//删除与 bulkdata 关系
mScanInfoList[scaninfo_idx].bookmark = -1;
for (int i = scaninfo_idx + 1; i < mScanInfoList.Count(); i++)
{
if (mScanInfoList[i].bookmark != -1)
{
int tmp = bookmark;
bookmark = mScanInfoList[i].bookmark;
mScanInfoList[i].bookmark = tmp;
}
}
}
}
}
FR_DATA_TYPE Direction2FR_DATA_TYPE(Misc.DIRECTION direction)
{
if (direction == DIRECTION.FORWARD)
return FR_DATA_TYPE.INVALID;
else
return FR_DATA_TYPE.VALID;
}
bool ToThicks(int scaninfo_idx)
{
ScanInfoCell scaninfo = mScanInfoList[scaninfo_idx];
if (scaninfo.IsFull)//所有grid数据都获取完,解方程
{
if (scaninfo.lockbm)
{
//不需要再解方程,算thicks 的值!!!
return false;
}
if (ToThicks_SolveEquation(scaninfo_idx))
{
//解方程成功
if (scaninfo.bookmark == -1)
scaninfo.bookmark = GetFreeBm();
//重新分区
if (IsNeedMap())
{
Dictionary map = new Dictionary();
for (int i = 0; i < Map.Count(); i++)
map.Add(Map[i].OldNo - 1, Map[i].NewNo - 1);
scaninfo.thicks_map = Misc.MyMath.Map(scaninfo.thicks, map);
}
//更新数据库内容
{
int[] frame;
List map;
if (IsNeedMap())
{
frame = scaninfo.thicks_map;
map = new List();
foreach (var m in Map)
map.Add(m.Clone());
}
else
{
frame = scaninfo.thicks;
map = null;
}
var realthicks = ToRealThicks(frame);
var renZiJiaDataEventArgs = new RenZiJiaDataEventArgs()
{
Time = scaninfo.thicks_dt,
EndTime = scaninfo.EndTime,
IsBackw = scaninfo.Direction == DIRECTION.BACKWARD,
RPeriod = mPDetect.RenZiJiaPeriod,
RCnt = mPDetect.RotationCnt,
OrgBoltNo = OrgBoltNo,
RAngle = mPDetect.RAngle,
FilmLength = mPDetect.FilmLength,
FilmVelocity = mPDetect.FilmVelocity,
K = mProfileParam.K,
Thicks = realthicks,
Boltmap = map
};
DataEvent?.Invoke(this, renZiJiaDataEventArgs);
//TODO 需要检查是否重复写入了!!!!!
#region sqlite3 历史数据保存
var lc_scandata = Lc_AutoMapperProfile.Mapper.Map(renZiJiaDataEventArgs);
mHistoryDb.AddScanData(lc_scandata);
#endregion
}
int[] thicks = IsNeedMap()? scaninfo.thicks_map:scaninfo.thicks;
if (scaninfo.bookmark == -1)
{
scaninfo.bookmark = mBulkData.Add(thicks, Direction2FR_DATA_TYPE(scaninfo.Direction), scaninfo.thicks_dt);
}
else
{
mBulkData.Change(scaninfo.bookmark, 0, thicks, Direction2FR_DATA_TYPE(scaninfo.Direction), scaninfo.thicks_dt);
}
mBulkData.Save();
}
else
{
//失败,删除!!!
for (int i = 0; i < scaninfo.thicks.Count(); i++)
scaninfo.thicks[i] = Misc.MyBase.NULL_VALUE;
if (scaninfo.bookmark != -1)
{
mBulkData.ChangeEmply(scaninfo.bookmark);
SetFreeBm(scaninfo.bookmark);
scaninfo.bookmark = -1;
}
}
scaninfo.lockbm = true;
return true;
}
else
{
//还没获取完所有grid, 简易解方程,只认为 mainBolt 是未知的,其它都是已知的,用上一幅数据的值
//这样的数据不需要放在数据库中!!!!!!
int[] org_thick = null;
if (scaninfo_idx != 0)
org_thick = mScanInfoList[scaninfo_idx - 1].thicks;
ScanInfoCell.SolveQuickResult result = scaninfo.SolveQuick(org_thick,SolveCnt-1);
if (result.len > 0)
{
//如果scaninfo.bookmark ==-1 ,也就是没有对应的 bulkdata 数据,创建一个
//先从freebm 获取,不行再创建新的
if (scaninfo.bookmark == -1)
scaninfo.bookmark = GetFreeBm();
if (scaninfo.bookmark == -1)
scaninfo.bookmark = mBulkData.AddEmply();
int[] thicks = scaninfo.thicks.Where((t, i) => (i >= result.start_index && i < (result.start_index + result.len))).ToArray();
mBulkData.Change(
scaninfo.bookmark,
result.start_index, thicks, Direction2FR_DATA_TYPE(scaninfo.Direction), scaninfo.thicks_dt);
mBulkDb.SetTempFrame(0, ToRealThicks(thicks));
}
}
return false;
}
///
/// 解方程
///
/// N条方程
/// 输出的结果
void SolveEquation(int[] frame_out, List equationList)
{
int nrow = equationList.Count();
//A~AX = A~B
//转换为 DenseMatrix 与 DenseVector
DenseMatrix matrixA = new DenseMatrix(nrow, NBolts);
DenseMatrix matrixAT = new DenseMatrix(NBolts, nrow);
DenseVector vectorB = new DenseVector(nrow);
DenseVector vectorATB = new DenseVector(NBolts);
int rowindex = 0;
foreach (EquationCell ec in equationList)
{
double[] datas = ec.GetPower(NBolts);
matrixA.SetRow(rowindex, datas);
matrixAT.SetColumn(rowindex, datas);
vectorB[rowindex] = ec.thick;
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++)
{
frame_out[i] = (int)X[i];
}
}
#endregion
///
/// 开始扫描
///
///
public override bool Start()
{
bool b = base.Start();
if (!b)
return false;
//设置扫描范围
int beginPos, endPos;
mBorderSearch.Init();
mBorderSearch.GetScanRange(out beginPos, out endPos);
ScanNo++;
//scanposdetect
mScanPosDetect.ScanNo = ScanNo;
//scaninfo
ScanInfoCell scaninfo = new ScanInfoCell(ScanNo, NBolts);
mScanInfoList.Add(scaninfo);
mBulkData.InitPush();
//清空临时数据
mBulkDb.SetTempFrame(0, null);
#region sqlite3 历史数据保存
CheckProfile();
mProfileParam.PropertyChanged += MProfileParam_PropertyChanged;
#endregion
return base.Start2(beginPos, endPos);
}
#region sqlite3 历史数据保存
string[] profile_propertynames_add = new string[]{
"PName",
"OrderNo",
"Number"
};
string[] profile_propertynames_update = new string[]{
"Target",
"TolerancePercent"
};
///
/// 检查产品信息更新情况,是否需要新加单,或者更新单信息
///
void CheckProfile()
{
if (mHistoryDb.localDb.IsProfileFinished)
{
//上一单结束了,添加新单
AddProfile();
}
else
{
if (mHistoryDb.localDb.CurrProfile != null)
{
Db_Profile db_Profile = mHistoryDb.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()
{
mHistoryDb.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()
{
mHistoryDb.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 (!mHistoryDb.localDb.IsProfileFinished)
{
mHistoryDb.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
///
/// 停止扫描
///
public override void Stop()
{
#region sqlite3 历史数据保存
mProfileParam.PropertyChanged -= MProfileParam_PropertyChanged;
#endregion
base.Stop();
//已经停止
//删除全部
mScanInfoList.Clear();
}
///
/// 周期动作处理
///
protected override void OnPoll()
{
base.OnPoll();
OnPoll_GetAngle();
}
///
/// 获取 缓冲区列表
///
/// retData 为
///
public void GetBufList(AsyncCBHandler AsyncDelegate, object AsyncState)
{
GetBufListReponse p = new GetBufListReponse();
p.lastbm = LastBM;
p.firstbm = FirstBM;
p.datas = mBufList;
AsyncDelegate(AsyncState, p);
}
}
///
/// 扫描位置检测
/// 里面的列表会缓存一些旧数据,如1次扫描前的位置信息。
/// 什么时候删除,由ScanPosDetect 自行决定,使用者不用关心
///
public class ScanPosDetect
{
///
/// IOStatus 推送出来扫描位置与时间
///
class PosCell
{
public DateTime dt;
public int position;
public override string ToString()
{
return dt.ToString() + " pos=" + position.ToString();
}
}
class PosCellList
{
public int scanNo;
private List mPosList = new List();
public void Add(int position, DateTime dt)
{
if (mPosList.Count() > 0)
{
if (mPosList.Last().position == position)
{
mPosList.Last().dt = dt;
return;
}
}
mPosList.Add(new PosCell() { position = position, dt = dt });
}
private DateTime GetTime(int position, int idx)
{
double d_pos = mPosList[idx].position - mPosList[idx + 1].position;
TimeSpan ts = mPosList[idx].dt - mPosList[idx + 1].dt;
long ticks = (long)((position - mPosList[idx + 1].position) / d_pos * ts.Ticks);
return mPosList[idx + 1].dt + new TimeSpan(ticks);
}
///
/// 获取位置对应的数据点.
/// 返回
/// -1:position在列表的前面;
/// 0:position在列表的里面
/// 1:position在列表的后面
///
///
///
///
public int GetTime(int position, out DateTime dt)
{
dt = DateTime.MinValue;
//TODO
if (mPosList.Count < 2)
return -1;
//通过列表最前面的数据,与最后面的数据,确认方向
DIRECTION direction;
if (mPosList.First().position < mPosList.Last().position)
direction = DIRECTION.FORWARD;
else
direction = DIRECTION.BACKWARD;
int idx;
if (direction == DIRECTION.FORWARD)
{
idx = mPosList.FindIndex(p => position <= p.position);
}
else
{
idx = mPosList.FindIndex(p => position >= p.position);
}
if (idx == -1)
{
//在列表后面
dt = GetTime(position, mPosList.Count - 2);
return 1;
}
else if (idx == 0)
{
//在列表前面
dt = GetTime(position, 0);
return -1;
}
else
{
//在列表里面
dt = GetTime(position, idx - 1);
return 0;
}
}
}
//TODO
private List mPosLists = new List();
private int lastGetTimeScanNo=-1;
private int scanNo;//当前扫描号。每扫描一次,scanNo++
public int ScanNo
{
get {
return scanNo;
}
set {
if (scanNo != value)
{
//Clear(ScanNo, -2);
scanNo = value;
}
}
}
///
/// 删除scanNo 偏移 offset 之前的数据
///
///
///
public void Clear(int scanNo,int offset)
{
if (mPosLists.Count == 0)//没数据
return;
int index = mPosLists.FindIndex(pl => pl.scanNo == scanNo);
if (index == -1)
return;//可能还没出现
index += offset;
if (index < 0)
return;//没有之前的数据
mPosLists.RemoveRange(0, index + 1);
}
public void Clear()
{
mPosLists.Clear();
}
public ScanPosDetect()
{
}
public void Init(IFlyAD flyad)
{
flyad.IStatusChangedEvent += new IStatusChangedEventHandler(flyad_IStatusChangedEvent);
}
void flyad_IStatusChangedEvent(object sender, IStatusChangedEventArgs e)
{
PosCellList poslist;
if (mPosLists.Count == 0)
mPosLists.Add(new PosCellList() { scanNo = ScanNo });
else
{
poslist = mPosLists.Last();
if (poslist.scanNo != ScanNo)
{
mPosLists.Add(new PosCellList() { scanNo = ScanNo });
}
}
poslist = mPosLists.Last();
poslist.Add(e.Position,e.Time);
//保持20个
//if (mPosLists.Count() > 20)
//{
// mPosLists.RemoveAt(0);
//}
}
///
/// 获取pos 对应的时间;
/// 返回 -1 数据在 列表前;
/// 返回 0 数据在列表内;
/// 返回 1 数据在列表外;
///
/// 位置
/// 扫描号
///
public int GetTime(int position, int scanNo, out DateTime dt)
{
if (lastGetTimeScanNo != scanNo)
{
//TODO
Clear(lastGetTimeScanNo, -8);
lastGetTimeScanNo = scanNo;
}
dt = DateTime.MinValue;
if (mPosLists.Count == 0)//没数据
return 1;
int d = scanNo - mPosLists[0].scanNo;
if (d < 0)
{
//发生在过去
//不正常
return -2;
}
int index = mPosLists.FindIndex(pl => pl.scanNo == scanNo);
if (index == -1)
return 1;//可能还没出现
PosCellList poslist = mPosLists[index];
int ret = poslist.GetTime(position, out dt);
if( (ret == 1) && (index != (mPosLists.Count - 1)))
return 0;
else if( (ret == -1) && (index != 0))
return 0;
else
return ret;
}
}
}