using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.ComponentModel; using FObjBase; using System.Collections.Specialized; namespace FLY.Thick.BulkDataModule { public class BulkDataService : IBulkDataService, IBulkDataServiceAdd { #region 成员变量 int m_size;//最大纵向幅数 int m_nbolts;//分区数 int m_boltno1st;//第1分区号 int pushmix_max = -1; /// <summary> /// 缓冲数据区 /// </summary> private List<FR_DATA> m_fr_data; public List<FR_DATA> Datas { get { return m_fr_data; } } public event NotifyDatasChangedEventHandler DatasChanged; private int count = 0; /// <summary> /// 数量 /// </summary> public int Count { get { return count; } set { if (count != value) { count = value; NotifyPropertyChanged("Count"); } } } private int currentbookmark = -1; /// <summary> /// 最新的bookmark /// </summary> public int CurrentBookmark { get { return currentbookmark; } set { if (currentbookmark != value) { currentbookmark = value; NotifyPropertyChanged("CurrentBookmark"); } } } #endregion private string param_path = "bulk.csv"; public BulkDataService(int nbolts, int boltno1st, int size) : this(nbolts, boltno1st, size, "bulk.csv") { } public BulkDataService(int nbolts, int boltno1st, int size, string param_path) { m_nbolts = nbolts; m_size = size; m_boltno1st = boltno1st; m_fr_data = new List<FR_DATA>(); if (!string.IsNullOrEmpty(param_path)) this.param_path = param_path; Load(); } #region ITDParam 成员 public bool Load() { if (!File.Exists(param_path)) return false; StreamReader sr = new StreamReader(param_path); string s = sr.ReadLine(); if (s == null) return false; //第1行,标题 //bookmark,time,type,0,1,2,3........... string[] ss = s.Split(new char[] { ',' }); int nbs = ss.Length - 3; if (nbs != NBolts) { sr.Close(); return false; // boltmap does not match! } int boltno1st; if (!int.TryParse(ss[3], out boltno1st)) return false; // boltmap does not match! BoltNo1st = boltno1st; m_fr_data.Clear(); int i = 0; while (!sr.EndOfStream) { if (i >= m_size) { sr.Close(); return true; } s = sr.ReadLine(); ss = s.Split(new char[] { ',' }); FR_DATA frdata = new FR_DATA(); if (!int.TryParse(ss[0], out frdata.bookmark)) { //失败,跳过 continue; } if (!DateTime.TryParse(ss[1], out frdata.timemark)) { //失败,跳过 continue; } int t; if (!int.TryParse(ss[2], out t)) { //失败,跳过 continue; } frdata.type = (FR_DATA_TYPE)t; frdata.m_data = new int[m_nbolts]; for (int j = 0; j < ss.Length - 3; j++) { if (j >= m_nbolts) break; string data_str = ss[j + 3]; if (string.IsNullOrWhiteSpace(data_str)) frdata.m_data[j] = Misc.MyBase.NULL_VALUE; else { if (!int.TryParse(ss[j + 3], out frdata.m_data[j])) frdata.m_data[j] = Misc.MyBase.NULL_VALUE; } } m_fr_data.Add(frdata); i++; } sr.Close(); return true; } public void Save() { if (string.IsNullOrEmpty(param_path)) return; StreamWriter sw = new StreamWriter(param_path, false); //第1行,标题 //bookmark, time, type, 0,1,2,3...... sw.Write("bookmark,time,type"); for (int i = 0; i < NBolts; i++) { sw.Write("," + (BoltNo1st+i).ToString()); } sw.WriteLine(); for (int i = 0; i < m_fr_data.Count; i++) { string s = m_fr_data[i].bookmark.ToString() + "," + m_fr_data[i].timemark.ToString("yyyy/MM/dd HH:mm:ss") + "," + ((int)m_fr_data[i].type).ToString() + ","; for (int j = 0; j < m_nbolts; j++) { if (Misc.MyBase.ISVALIDATA(m_fr_data[i].m_data[j])) s += m_fr_data[i].m_data[j].ToString(); if (j != m_nbolts - 1) s += ","; } sw.WriteLine(s); } sw.Flush(); sw.Close(); return; } #endregion #region IBulkDataService /// <summary> /// 注册新数据推送 /// </summary> /// <param name="param"></param> /// <param name="AsyncDelegate"></param> /// <param name="AsyncState"></param> public void PushNewFrameData( BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam param, AsyncCBHandler AsyncDelegate, object AsyncState) { if (!dataRequestList.Exists(dr => dr.AsyncState.Equals(AsyncState) && IsSameParam(dr.Param, param))) { dataRequestList.Add( new DataRequest() { Param = param, AsyncState = AsyncState, AsyncDelegate = AsyncDelegate }); } } void GetNewFrameData(BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam param, AsyncCBHandler AsyncDelegate, object AsyncState) { int[] result; if (pushmix_max < 1) return; int mix = (param.mix < pushmix_max) ? param.mix : pushmix_max; GetFrame(out result, -1, param.mix, 0, NBolts); BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataReturn reponse = new BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataReturn() { mix = param.mix }; FR_DATA frdata = GetBulkFrame(-1); if (frdata != null) { reponse.bookmark = frdata.bookmark;//结果对应的 bookmark reponse.dt = frdata.timemark;//结果对应的 时间 reponse.type = frdata.type;//结果.数据是否有效 reponse.result = result;//结果, 当needPush=true, 以后推送时,只发送变化了的数据 } AsyncDelegate(AsyncState, reponse); } /// <summary> /// 获取一幅数据, 默认带推送 /// </summary> /// <param name="param"></param> /// <param name="AsyncDelegate"></param> /// <param name="AsyncState"></param> public void GetFrameData(BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam param, AsyncCBHandler AsyncDelegate, object AsyncState) { if (param.NeedPush)//推送 { if (!dataRequestList.Exists(dr => dr.AsyncState.Equals(AsyncState) && IsSameParam(dr.Param, param))) { dataRequestList.Add( new DataRequest() { Param = param, AsyncState = AsyncState, AsyncDelegate = AsyncDelegate }); } } int[] result; GetFrame(out result, param.bm, param.mix, 0, NBolts); BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataReturn reponse = new BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataReturn() { NeedPush = param.NeedPush, bm = param.bm, mix = param.mix }; FR_DATA frdata = GetBulkFrame(param.bm); if (frdata != null) { reponse.bookmark = frdata.bookmark;//结果对应的 bookmark reponse.dt = frdata.timemark;//结果对应的 时间 reponse.fromBoltIndex = 0;//开始分区index reponse.toBoltIndex = result.Length - 1;//结束分区index reponse.type = frdata.type;//结果.数据是否有效 reponse.result = result;//结果, 当needPush=true, 以后推送时,只发送变化了的数据 } AsyncDelegate(AsyncState, reponse); } void GetFrameData(BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam param, AsyncCBHandler AsyncDelegate, object AsyncState, int boltIndex, int len) { int[] result; GetFrame(out result, param.bm, param.mix, boltIndex, len); BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataReturn reponse = new BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataReturn() { NeedPush = param.NeedPush, bm = param.bm, mix = param.mix }; FR_DATA frdata = GetBulkFrame(param.bm); if (frdata != null) { reponse.bookmark = frdata.bookmark;//结果对应的 bookmark reponse.dt = frdata.timemark;//结果对应的 时间 reponse.fromBoltIndex = boltIndex;//开始分区index reponse.toBoltIndex = boltIndex + len - 1;//结束分区index reponse.type = frdata.type;//结果.数据是否有效 reponse.result = result;//结果, 当needPush=true, 以后推送时,只发送变化了的数据 } AsyncDelegate(AsyncState, reponse); } bool IsSameParam_PushNewFrameData(object src, object dest) { if ((src is BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam) && (dest is BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam)) { BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam fdparam = src as BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam; BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam cfdparam = dest as BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam; if (fdparam.mix == cfdparam.mix) { return true; } else { return false; } } return false; } bool IsSameParam_GetFrameData(object src, object dest) { if ((src is BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData) && (dest is BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData)) { BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData fdparam = src as BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData; BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData cfdparam = dest as BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData; if ((fdparam.bm == cfdparam.bm) && (fdparam.mix == cfdparam.mix)) { return true; } else { return false; } } return false; } bool IsSameParam_GetTrendData(object src, object dest) { if ((src is BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData) && (dest is BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData)) { BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData tdparam = src as BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData; BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData ctdparam = dest as BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData; if ((tdparam.mix == ctdparam.mix) && (tdparam.fromBoltNo == ctdparam.fromBoltNo) && (tdparam.toBoltNo == ctdparam.toBoltNo)) { return true; } else { return false; } } return false; } bool IsSameParam_GetFrameDataMix(object src, object dest) { if ((src is Pack_CallClosePushFrameDataMixRequest) && (dest is Pack_CallClosePushFrameDataMixRequest)) { return ((Pack_CallClosePushFrameDataMixRequest)src).IsSame( (Pack_CallClosePushFrameDataMixRequest)dest); } return false; } bool IsSameParam(object src, object dest) { if (IsSameParam_GetFrameData(src, dest) == true) return true; if (IsSameParam_GetTrendData(src, dest) == true) return true; if (IsSameParam_PushNewFrameData(src, dest) == true) return true; if (IsSameParam_GetFrameDataMix(src, dest) == true) return true; return false; } /// <summary> /// 获取纵向趋势图,默认带推送 /// </summary> /// <param name="param"></param> /// <param name="AsyncDelegate"></param> /// <param name="AsyncState"></param> public void GetTrendData(BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam param, AsyncCBHandler AsyncDelegate, object AsyncState) { if (param.NeedPush) { if (!dataRequestList.Exists(dr => dr.AsyncState.Equals(AsyncState) && IsSameParam(dr.Param, param))) { dataRequestList.Add( new DataRequest() { Param = param, AsyncState = AsyncState, AsyncDelegate = AsyncDelegate }); } } TrendDataCell[] result; GetTrend(out result, param.len, param.mix, param.fromBoltNo, param.toBoltNo); BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn reponse = new BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn(); reponse.NeedPush = param.NeedPush;//当数据变化时,是否需要推送 reponse.len = param.len;//获取的长度 reponse.mix = param.mix;//混合数 reponse.fromBoltNo = param.fromBoltNo;//开始分区index reponse.toBoltNo = param.toBoltNo;//结束分区index //TODO //输出 //FR_DATA frdata = GetBulkFrame(-1); //if (frdata != null)//有数据,不是空的!!!!! //{ if(result != null) { reponse.edit_position = 0; reponse.result = result;//结果 } AsyncDelegate(AsyncState, reponse); } /// <summary> /// 关闭 扫描图 推送 /// </summary> /// <param name="param"></param> /// <param name="AsyncState"></param> public void ClosePushFrameData(BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData param, object AsyncState) { dataRequestList.RemoveAll( dr => dr.AsyncState.Equals(AsyncState) && IsSameParam(dr.Param, param)); } /// <summary> /// 关闭 新数据推送 /// </summary> /// <param name="param"></param> /// <param name="AsyncState"></param> public void ClosePushNewFrameData(BULKDATA_OBJ_INTERFACE.Pack_CallClosePushNewFrameData param, object AsyncState) { dataRequestList.RemoveAll( dr => dr.AsyncState.Equals(AsyncState) && IsSameParam(dr.Param, param)); } /// <summary> /// 关闭 纵向趋势图 推送 /// </summary> /// <param name="param"></param> /// <param name="AsyncState"></param> public void ClosePushTrendData(BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData param, object AsyncState) { dataRequestList.RemoveAll( dr => dr.AsyncState.Equals(AsyncState) && IsSameParam(dr.Param, param)); } /// <summary> /// 获取一幅数据, 默认带推送 /// 参数 Pack_CallGetFrameDataMixRequest /// 回复 Pack_CallGetFrameDataMixReponse /// </summary> /// <param name="param"></param> /// <param name="AsyncDelegate"></param> /// <param name="AsyncState"></param> public void GetFrameDataMix( Pack_CallGetFrameDataMixRequest param, AsyncCBHandler AsyncDelegate, object AsyncState) { if (param.NeedPush)//推送 { if (!dataRequestList.Exists(dr => dr.AsyncState.Equals(AsyncState) && IsSameParam(dr.Param, param))) { dataRequestList.Add( new DataRequest() { Param = param, AsyncState = AsyncState, AsyncDelegate = AsyncDelegate }); } } GetFrameDataMix(param, AsyncDelegate, AsyncState, 0, NBolts); } void GetFrameDataMix(Pack_CallGetFrameDataMixRequest param, AsyncCBHandler AsyncDelegate, object AsyncState, int boltIndex, int len) { FrameDataCell[] result; int start_bookmark; GetFrameMix(out result,out start_bookmark, param.bm, param.mix, boltIndex, len, param.start_dt); Pack_CallGetFrameDataMixReponse reponse = new Pack_CallGetFrameDataMixReponse() { NeedPush = param.NeedPush, bm = param.bm, mix = param.mix, start_dt = param.start_dt }; FR_DATA frdata = GetBulkFrame(param.bm); if (frdata != null) { reponse.bookmark = frdata.bookmark;//结果对应的 bookmark reponse.dt = frdata.timemark;//结果对应的 时间 reponse.fromBoltIndex = boltIndex;//开始分区index reponse.toBoltIndex = boltIndex + len - 1;//结束分区index reponse.type = frdata.type;//结果.数据是否有效 reponse.result = result;//结果, 当needPush=true, 以后推送时,只发送变化了的数据 FR_DATA start_frdata = GetBulkFrame(start_bookmark); reponse.act_startDt = start_frdata.timemark;//结果对应的 实际开始时间 } AsyncDelegate(AsyncState, reponse); } /// <summary> /// 关闭 扫描图 推送 /// </summary> /// <param name="param"></param> /// <param name="AsyncState"></param> public void ClosePushFrameDataMix( Pack_CallClosePushFrameDataMixRequest param, object AsyncState) { dataRequestList.RemoveAll( dr => dr.AsyncState.Equals(AsyncState) && IsSameParam(dr.Param, param)); } /// <summary> /// 只要关于AsyncState 的都要删除 /// </summary> /// <param name="match"></param> public void ClosePush(Predicate<object> match) { dataRequestList.RemoveAll(delegate(DataRequest dr) { return match(dr.AsyncState); }); } /// <summary> /// 清空缓存 /// </summary> public void Clear() { m_fr_data.Clear(); ClearedEvent(); } /// <summary> /// 准备好,只有在 IsReady=true ,发送的命令才能执行,才能推送 /// </summary> public bool IsReady { get { return true; } } /// <summary> /// 全部数据被删除 /// </summary> void ClearedEvent() { CurrentBookmark = -1; Count = 0; { DatasChanged?.Invoke( this, new NotifyDatasChangedEventArgs() { Action = NotifyDatasChangedAction.Reset }); } foreach (DataRequest dr in dataRequestList) { if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam fdp = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam; BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataReturn reqonse = new BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataReturn(); reqonse.NeedPush =fdp.NeedPush;//当数据变化时,是否需要推送 reqonse.bm = fdp.bm;//标记, 当bm>0 为bookmark,当bm <=0 为往前面数 reqonse.mix = fdp.mix;//混合数 //输出 reqonse.bookmark = -1;//结果对应的 bookmark reqonse.dt = DateTime.MinValue;//结果对应的 时间 reqonse.fromBoltIndex = 0;//开始分区index reqonse.toBoltIndex = NBolts - 1;//结束分区index reqonse.type = FR_DATA_TYPE.INVALID;//结果.数据是否有效 reqonse.result = null;//结果, 当needPush=true, 以后推送时,只发送变化了的数据 dr.AsyncDelegate(dr.AsyncState, reqonse); } else if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam tdp = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam; BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn reqonse = new BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn(); reqonse.NeedPush = tdp.NeedPush;//当数据变化时,是否需要推送 reqonse.len = tdp.len;//获取的长度 reqonse.mix = tdp.mix;//混合数 reqonse.fromBoltNo = tdp.fromBoltNo;//开始分区index reqonse.toBoltNo = tdp.toBoltNo;//结束分区index //输出 reqonse.edit_position = 0; reqonse.result = null;//结果 dr.AsyncDelegate(dr.AsyncState, reqonse); } } } bool IsFit(DataRequest dr , int bm_relative) { if(dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam fdp = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam; int fdp_bm_relative = BM2Relative(fdp.bm); if ((fdp_bm_relative - fdp.mix < bm_relative) && (fdp_bm_relative >= bm_relative)) return true; else return false; } else if(dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam tdp = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam; if((BM2Relative(-1) - tdp.mix <bm_relative) && (BM2Relative(-1) >= bm_relative)) return true; else return false; } return false; } /// <summary> /// 某幅数据被修改 /// </summary> void ChangedEvent(FR_DATA fr_data, int boltIndex, int len) { { int idx = Datas.FindLastIndex((d) => d == fr_data); DatasChanged?.Invoke( this, new NotifyDatasChangedEventArgs() { Action = NotifyDatasChangedAction.Replace, Items = new List<FR_DATA>(new FR_DATA[] { fr_data }), NewStartingIndex = idx }); } int bookmark = fr_data.bookmark; int bm_relative = BM2Relative(bookmark); var drs = from _dr in dataRequestList where IsFit(_dr, bm_relative) select _dr; if (drs.Count() > 0) { foreach (DataRequest dr in drs) { if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam param = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam; GetFrameData( param, dr.AsyncDelegate, dr.AsyncState, boltIndex, len); } else if (dr.Param is Pack_CallGetFrameDataMixRequest) { Pack_CallGetFrameDataMixRequest param = dr.Param as Pack_CallGetFrameDataMixRequest; GetFrameDataMix( param, dr.AsyncDelegate, dr.AsyncState, boltIndex, len); } else if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam param = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam; //GetTrend只能获取 BM= -1 的数据,其它不管 if (bm_relative > -1) return; if(bm_relative<-param.mix) return; //判断是否有交集 int fromBoltIndex = boltIndex; int toBoltIndex = boltIndex + len - 1; int ts1 = (param.fromBoltNo-BoltNo1st) - fromBoltIndex; int ts2; if (ts1 > 0)// fromBoltIndex < param.fromBoltIndex ts2 = (param.fromBoltNo - BoltNo1st) - toBoltIndex; else// param.fromBoltIndex < fromBoltIndex ts2 = fromBoltIndex - (param.toBoltNo - BoltNo1st); if (ts2 > 0) return;//无交集 TrendDataCell[] result; GetTrend(out result, param.mix, param.mix, param.fromBoltNo, param.toBoltNo); if (result.Length == 0) continue; BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn reponse = new BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn(); reponse.NeedPush = param.NeedPush;//当数据变化时,是否需要推送 reponse.len = param.len;//获取的长度 reponse.mix = param.mix;//混合数 reponse.fromBoltNo = param.fromBoltNo;//开始分区index reponse.toBoltNo = param.toBoltNo;//结束分区index //输出 FR_DATA frdata = GetBulkFrame(bookmark); reponse.edit_position = 0; reponse.result = result;//结果 dr.AsyncDelegate(dr.AsyncState, reponse); } } } } bool IsFit2(DataRequest dr) { if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam fdp = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam; if (fdp.bm <= 0) return true; else return false; } else if (dr.Param is Pack_CallGetFrameDataMixRequest) { Pack_CallGetFrameDataMixRequest fdp = dr.Param as Pack_CallGetFrameDataMixRequest; if (fdp.bm <= 0) return true; else return false; } else if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam) { return true; } else if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam) { return true; } return false; } /// <summary> /// 添加了一幅数据, 推送数据 /// </summary> void AddedEvent() { Count = Datas.Count(); CurrentBookmark = Datas.Last().bookmark; { DatasChanged?.Invoke( this, new NotifyDatasChangedEventArgs() { Action = NotifyDatasChangedAction.Add, Items = new List<FR_DATA>(new FR_DATA[] { Datas.Last() }), NewStartingIndex = Datas.Count() - 1 }); } var drs = from _dr in dataRequestList where IsFit2(_dr) select _dr; if (drs.Count() > 0) { foreach (DataRequest dr in drs) { if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam param = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam; GetNewFrameData( dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam, dr.AsyncDelegate, dr.AsyncState); } else if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam param = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam; GetFrameData( param, dr.AsyncDelegate, dr.AsyncState, 0, NBolts); } else if (dr.Param is Pack_CallGetFrameDataMixRequest) { Pack_CallGetFrameDataMixRequest param = dr.Param as Pack_CallGetFrameDataMixRequest; GetFrameDataMix( param, dr.AsyncDelegate, dr.AsyncState, 0, NBolts); } else if (dr.Param is BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam) { BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam param = dr.Param as BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam; TrendDataCell[] result; GetTrend(out result, 1, param.mix, param.fromBoltNo, param.toBoltNo); if (result == null) continue; if (result.Length == 0) continue; BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn reponse = new BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn(); reponse.NeedPush = param.NeedPush;//当数据变化时,是否需要推送 reponse.len = param.len;//获取的长度 reponse.mix = param.mix;//混合数 reponse.fromBoltNo = param.fromBoltNo;//开始分区index reponse.toBoltNo = param.toBoltNo;//结束分区index //输出 //FR_DATA frdata = GetBulkFrame(-1); reponse.edit_position = 1; reponse.result = result;//结果 dr.AsyncDelegate(dr.AsyncState, reponse); } } } } #endregion #region IBulkDataService class DataRequest { public object Param; public object AsyncState; public AsyncCBHandler AsyncDelegate; } List<DataRequest> dataRequestList = new List<DataRequest>(); #endregion #region bookmark 取值 int GetCurrentBookmark() { FR_DATA frdata = m_fr_data.Last(); if (frdata == null) return -1; return frdata.bookmark; } /// <summary> /// 最大bookmark /// </summary> int MaxBookmark { get { return 4000; } } /// <summary> /// 最小bookmark /// </summary> int MinBookmark { get { return 1; } } /// <summary> /// 获取下一个bookmark ,bookmark的取值范围 MinBookmark~MaxBookmark,反正 大于 0 /// </summary> /// <param name="bookmark"></param> /// <returns></returns> int GetNextBookmark(int bookmark) { if (bookmark < 0) return 1; bookmark++; if (bookmark > MaxBookmark) bookmark = MinBookmark; return bookmark; } /// <summary> /// 获取上一个bookmark,bookmark的取值范围 MinBookmark~MaxBookmark,反正 大于 0 /// </summary> /// <param name="bookmark"></param> /// <returns></returns> int GetPreBookmark(int bookmark) { if (bookmark < 0) return 1; bookmark--; if (bookmark < MinBookmark) bookmark = MaxBookmark; return bookmark; } #endregion int GetBulkBookmark(int bm) { FR_DATA frdata = GetBulkFrame(bm); if (frdata == null) { return -1; } return frdata.bookmark; } /// <summary> /// 当bm>0,获取 bookmark=bm 的数据 /// 当bm<=0, 获取 bookmark= 最新的数据bookmark-bm /// </summary> /// <param name="bm"></param> /// <returns></returns> FR_DATA GetBulkFrame(int bm) { if (m_fr_data.Count == 0) return null; int bookmark = BM2Bookmark(bm); try { return m_fr_data.Find(dat => dat.bookmark == bookmark); } catch { return null; } } /// <summary> /// 当bm>0,返回 bookmark /// 当bm<=0,返回 bm + 最新的数据bookmark /// </summary> /// <param name="bm"></param> /// <returns></returns> int BM2Bookmark(int bm) { if (bm > 0) { return bm; } else { int bookmark = GetCurrentBookmark(); bookmark += bm; if (bookmark < MinBookmark) { bookmark = MaxBookmark - (MinBookmark - bookmark - 1); } return bookmark; } } /// <summary> /// 用于比较; /// 当bm>0,返回 bm - 最新的数据bookmark /// 当bm<=0,返回 bm; /// </summary> /// <param name="bm"></param> /// <returns></returns> int BM2Relative(int bm) { if (bm <= 0) return bm; else { int bookmark = bm; int current = GetCurrentBookmark(); int d = bookmark - current; if (d > 0) { d -= (MaxBookmark - MinBookmark + 1); } return d; } } /// <summary> /// 获取纵向趋势图, 数据是从后向前排的,[0]是最新的数据 /// </summary> /// <param name="result">输出结果</param> /// <param name="len">result的长度</param> /// <param name="mix">混合数</param> /// <param name="avg_from">求平均值 开始的分区No</param> /// <param name="avg_to">求平均值 结束的分区No</param> /// <returns></returns> bool GetTrend(out TrendDataCell[] result, int len, int mix, int avg_from, int avg_to) { if (mix <= 0) mix = 1; int bookmark = -1; //错误纠正 if((!Misc.MyBase.ISVALIDATA(avg_from)) || (!Misc.MyBase.ISVALIDATA(avg_to))) { avg_from = 0; avg_to = NBolts; } else { avg_from -= BoltNo1st; avg_to -= BoltNo1st; if (avg_from < 0 || avg_to < 0) { avg_from = 0; avg_to = NBolts; } else if (avg_to < avg_from) { int t = avg_to; avg_to = avg_from; avg_from = t; } } //------------------------------------------------------------------------------------------------ //类型不一样,不能混合 FR_DATA_TYPE type; DateTime time; List<TrendDataCell> _result = new List<TrendDataCell>(); int i = 0; for (i = 0; i < len; i++) { FR_DATA fr_data = GetBulkFrame(bookmark); if (fr_data == null) break; bookmark = fr_data.bookmark; type = fr_data.type; time = fr_data.timemark; int bm = bookmark; List<int> datas = new List<int>(); int k; for (k = 0; k < mix; k++) { if (k > 0) { fr_data = GetBulkFrame(bm); if (fr_data == null) break; //different type can`t mix together~~~~~~~~~~~~~~~~~~~~ if (fr_data.type != type) break; } //int dat; //dat = Misc.MyMath.Avg(fr_data.m_data, avg_from, avg_to); datas.AddRange(fr_data.m_data.Skip(avg_from).Take(avg_to - avg_from + 1)); bm = GetPreBookmark(bm); } //LogMessage2("bulkdata.c",1,"GetFixData mix=%d i=%d type=%d cnt=%d",mix,i,type,cnt); int avg = Misc.MyMath.Avg(datas.ToArray()); int sigma = Misc.MyMath.Sigma(datas.ToArray()); _result.Add( new TrendDataCell() { Avg = avg, Sigma = sigma, Time = time, Type = type }); bookmark = GetPreBookmark(bookmark); } if (_result.Count == 0) { result = null; return false; } result = _result.ToArray(); return true; } //获取混合曲线 bool GetFrame(out int[] result, int bm, int mix, int start_boltIndex, int len) { if (mix < 0) mix = 1; result = null; FR_DATA fr_data = GetBulkFrame(bm); if (fr_data == null) return false; int bookmark = fr_data.bookmark; //------------------------------------------------------------------------------------------------ //类型不一样,不能混合 FR_DATA_TYPE type = fr_data.type; List<FR_DATA> fr_datas = new List<FR_DATA>(); result = new int[len]; int i; for (i = 0; i < mix; i++) { if (i > 0) { fr_data = GetBulkFrame(bookmark); if (fr_data == null) break; if (fr_data.type != type) break; } fr_datas.Add(fr_data); bookmark = GetPreBookmark(bookmark); } mix = i; int j; for (j = start_boltIndex; (j < (start_boltIndex + len)) && (j < m_nbolts); j++) { int sum = 0; int cnt = 0; for (i = 0; i < mix; i++) { int dat = fr_datas[i].m_data[j]; if (Misc.MyBase.ISVALIDATA(dat)) { sum += dat; cnt++; } } if (cnt > 0) { result[j - start_boltIndex] = sum / cnt; } else { result[j - start_boltIndex] = Misc.MyBase.NULL_VALUE; } } return true; } //获取混合曲线 bool GetFrameMix(out FrameDataCell[] result,out int start_bookmark, int bm, int mix, int start_boltIndex, int len, DateTime start_dt) { if (mix < 0) mix = 1; result = null; start_bookmark = -1; FR_DATA fr_data = GetBulkFrame(bm); if (fr_data == null) return false; //------------------------------------------------------------------------------------------------ //就算start_dt 是在未来的,也要有一幅数据 if (fr_data.timemark < start_dt)//时间不对 start_dt = fr_data.timemark; int bookmark = fr_data.bookmark; //------------------------------------------------------------------------------------------------ //类型不一样,不能混合 FR_DATA_TYPE type = fr_data.type; List<FR_DATA> fr_datas = new List<FR_DATA>(); result = new FrameDataCell[len]; int i; for (i = 0; i < mix; i++) { if (i > 0) { fr_data = GetBulkFrame(bookmark); if (fr_data == null) break; if (fr_data.type != type) break; if (fr_data.timemark < start_dt)//时间不对 break; } fr_datas.Add(fr_data); start_bookmark = bookmark; bookmark = GetPreBookmark(bookmark); } mix = i; List<int> datas = new List<int>(); int j; for (j = start_boltIndex; (j < (start_boltIndex + len)) && (j < m_nbolts); j++) { for (i = 0; i < mix; i++) { int dat = fr_datas[i].m_data[j]; datas.Add(dat); } FrameDataCell r = new FrameDataCell(); r.Avg = Misc.MyMath.Avg(datas); r.Sigma = Misc.MyMath.Sigma(datas); datas.Clear(); result[j - start_boltIndex] = r; } return true; } #region IBulkDataServiceAdd public int NBolts { get { return m_nbolts; } set { if (m_nbolts != value) { Clear(); m_nbolts = value; NotifyPropertyChanged("NBolts"); } } } public int BoltNo1st { get { return m_boltno1st; } set { if (m_boltno1st != value) { Clear(); m_boltno1st = value; NotifyPropertyChanged("BoltNo1st"); } } } public void InitPush() { pushmix_max = -1; } public int Add(int[] buf, FR_DATA_TYPE type, DateTime dt) { if (m_fr_data.Count > m_size) m_fr_data.RemoveAt(0); int bm; if (m_fr_data.Count > 0) { bm = GetNextBookmark(m_fr_data.Last().bookmark); } else { bm = GetNextBookmark(-1); } FR_DATA frdata = new FR_DATA(bm, buf, type); frdata.timemark = dt; m_fr_data.Add(frdata); if (pushmix_max < (m_fr_data.Count() - 1)) pushmix_max++; AddedEvent(); return GetBulkBookmark(0); } public int Add(int[] buf, FR_DATA_TYPE type) { return Add(buf, type, DateTime.Now); } public int AddEmply() { int[] buf = new int[NBolts]; for (int i = 0; i < NBolts; i++) { buf[i] = Misc.MyBase.NULL_VALUE; } return Add(buf, FR_DATA_TYPE.INVALID); } public bool Change(int bm, int start_boltIndex, int[] buf, FR_DATA_TYPE type, DateTime time) { FR_DATA fr_data = GetBulkFrame(bm); if (fr_data == null) return false; //bool debug = false; //if (m_fr_data.Count > 1 && bm == 1) //{ // for (int i = 0; i < buf.Count(); i++) // { // if (buf[i] != fr_data.m_data[i]) // { // //找到了 // debug = true; // break; // } // } //} //if (debug) //{ //} fr_data.type = type; if(time != DateTime.MinValue) fr_data.timemark = time; Array.Copy(buf, 0, fr_data.m_data, start_boltIndex, buf.Length); //if (debug) //{ // debug = false; // for (int i = 0; i < buf.Count(); i++) // { // if (buf[i] != fr_data.m_data[i]) // { // //异常 // debug = true; // break; // } // } // if (debug) // { // } //} ChangedEvent(fr_data, start_boltIndex, buf.Length); return true; } public bool Change(int bm, int start_boltIndex, int[] buf, FR_DATA_TYPE type) { return Change(bm, start_boltIndex, buf, type, DateTime.MinValue); } public bool ChangeEmply(int bm) { int[] buf = new int[NBolts]; for (int i = 0; i < NBolts; i++) { buf[i] = Misc.MyBase.NULL_VALUE; } return Change(bm, 0, buf, FR_DATA_TYPE.INVALID); } public bool ChangeEmply() { int[] buf = new int[NBolts]; for (int i = 0; i < NBolts; i++) { buf[i] = Misc.MyBase.NULL_VALUE; } return Change(0, 0, buf, FR_DATA_TYPE.INVALID, DateTime.Now); } #endregion #region INotifyPropertyChanged 成员 protected void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; #endregion } }