/// <summary> /// parse the fragment string, /// "start=t1&end=t2&decimation=2" decimation is optional /// </summary> /// <param name="fragment"></param> /// <returns></returns> public static WaveFragment Parse(string fragment) { //"start=t1&end=t2&decimation=2&count=1000" decimation is optional if (fragment.StartsWith("#")) { fragment = fragment.Substring(1); } var sections = fragment.Split(new char[] { '&' }); var result = new WaveFragment { DecimationFactor = 1, Start = 0, End = 0, Count = 0 }; foreach (var sec in sections) { if (sec.Contains("start")) { result.Start = double.Parse(sec.Substring(6)); } if (sec.Contains("end")) { result.End = double.Parse(sec.Substring(4)); } if (sec.Contains("decimation")) { result.DecimationFactor = long.Parse(sec.Substring(11)); } if (sec.Contains("count")) { result.Count = long.Parse(sec.Substring(6)) > 0 ? long.Parse(sec.Substring(6)) : 0; } } return result; }
/// <summary> /// 使用Cursor读取大数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="signal"></param> /// <param name="fragment"></param> /// <returns></returns> public async Task<ICursor> GetCursorAsync<T>(Signal signal, string fragment) { //var waveSig = signal as FixedIntervalWaveSignal<T>; var waveSig = signal as FixedIntervalWaveSignal; if (waveSig == null) { throw new Exception(ErrorMessages.NotValidSignalError); } WaveFragment frag = null; try { frag = WaveFragment.Parse(fragment); } catch (Exception) { throw new Exception(ErrorMessages.NotValidSignalFragmentError); } //end smaller then start then read all if (frag.Start >= frag.End) { frag.Start = waveSig.StartTime; frag.End = waveSig.EndTime; } //calc the decimationfactor is count valid if (frag.Count > 0) { //todo can be optimized a little frag.DecimationFactor = (long)Math.Floor(((frag.End - frag.Start) / waveSig.SampleInterval + 1) / frag.Count); } if (frag.DecimationFactor < 1) { frag.DecimationFactor = 1; } var startIndex = (long)Math.Ceiling((frag.Start - waveSig.StartTime) / waveSig.SampleInterval); var count = (long)Math.Floor((frag.End - frag.Start) / waveSig.SampleInterval / frag.DecimationFactor) + 1; return await myStorageEngine.GetCursorAsync<T>(waveSig.Id, new List<long> { startIndex }, new List<long> { count }, new List<long> { frag.DecimationFactor }); }
/// <summary> /// format is "array"(default) or "complex" /// review 这个下面很多代码和get curser重复了,可以修改 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="signal"></param> /// <param name="fragment">fragment: "start=t1&end=t2&decimation=2&count=1000" decimation is optional, if end is no bigger then start then return all</param> /// <param name="format">format is "array"(default) or "complex" </param> /// <returns></returns> public async Task<object> GetDataAsync<T>(Signal signal, string fragment, string format) { //var waveSig = signal as FixedIntervalWaveSignal<T>; var waveSig = signal as FixedIntervalWaveSignal; if (waveSig == null) { throw new Exception(ErrorMessages.NotValidSignalError); } WaveFragment frag = null; try { frag = WaveFragment.Parse(fragment); } catch (Exception) { throw new Exception("Fragment parse error!"); } //end smaller then start then read all if (frag.Start >= frag.End) { frag.Start = waveSig.StartTime; frag.End = waveSig.EndTime; } if (frag.Start < waveSig.StartTime) { frag.Start = waveSig.StartTime; } if (frag.End > waveSig.EndTime) { frag.End = waveSig.EndTime; } //calc the decimationfactor is count valid if (frag.Count > 0) { //todo can be optimized a little frag.DecimationFactor = (long)Math.Floor(((frag.End - frag.Start) / waveSig.SampleInterval + 1) / frag.Count); } if (frag.DecimationFactor < 1) { frag.DecimationFactor = 1; } var startIndex = (long)Math.Ceiling((frag.Start - waveSig.StartTime) / waveSig.SampleInterval); var count = (long)Math.Floor((frag.End - frag.Start) / waveSig.SampleInterval / frag.DecimationFactor) + 1; ICursor<T> cursor = await myStorageEngine.GetCursorAsync<T>(waveSig.Id, new List<long> { startIndex }, new List<long> { count }, new List<long> { frag.DecimationFactor }); List<T> resultArray = new List<T>(); //防止读时越界 review cursor 目前一次只能读1000个点? while (cursor.LeftPoint > 1000) { resultArray.AddRange(await cursor.Read(1000)); } if (cursor.LeftPoint > 0) { resultArray.AddRange(await cursor.Read(cursor.LeftPoint)); } if (format == "complex") { return new FixedIntervalWaveComplex<T> { Title = waveSig.Path, Start = startIndex * waveSig.SampleInterval + waveSig.StartTime, End = waveSig.StartTime + ((count - 1) * frag.DecimationFactor + startIndex) * waveSig.SampleInterval, Count = count, Data = resultArray, DecimatedSampleInterval = waveSig.SampleInterval * frag.DecimationFactor, OrignalSampleInterval = waveSig.SampleInterval, DecimationFactor = frag.DecimationFactor, StartIndex = startIndex, Unit = waveSig.Unit }; } else if (format == "point") { var points = new List<SignalPoint<T>>(); // 计算首尾所需取的采样间隔(一致)、点数 //bug review 这里是不是也有点重复?,我也没看懂,我大概的理解是,不管用户请求什么数据,都把全部的数据返回给用户,不过用户请求区域以外的数据,点数更加稀疏一些(100个点?)?这个逻辑和其他的读取不一样呀,有问题!!! long headtailDecimationFactor = 0; long headtailMaxCount = 100; if ((frag.Start - waveSig.StartTime) > (waveSig.EndTime - frag.End)) { headtailDecimationFactor = (long)Math.Floor(((frag.Start - waveSig.StartTime) / waveSig.SampleInterval + 1) / headtailMaxCount); } else { headtailDecimationFactor = (long)Math.Floor(((waveSig.EndTime - frag.End) / waveSig.SampleInterval + 1) / headtailMaxCount); } if (headtailDecimationFactor < 1) { headtailDecimationFactor = 1; } var headCount = (long)Math.Floor((frag.Start - waveSig.StartTime) / waveSig.SampleInterval / headtailDecimationFactor) + 1; var tailCount = (long)Math.Floor((waveSig.EndTime - frag.End) / waveSig.SampleInterval / headtailDecimationFactor) + 1; //添加前段概略点 double x = waveSig.StartTime; if (headCount > 1) { ICursor<T> headCursor = await myStorageEngine.GetCursorAsync<T>(waveSig.Id, new List<long> { 0 }, new List<long> { headCount }, new List<long> { headtailDecimationFactor }); //review 这里不应该用foreach,顺序不定,而且即使用循环也不太好,效率有点低,不过好像也没什么别的办法,最好还是不要生成x序列,太浪费服务器资源了,以后,以后我们前端最好还是不要用这个point foreach (var data in await headCursor.Read(headCursor.LeftPoint)) { points.Add(new SignalPoint<T>(x, data)); x += waveSig.SampleInterval * headtailDecimationFactor; } } //添加中间详细点 x = frag.Start; foreach (var data in resultArray) { points.Add(new SignalPoint<T>(x, data)); x += waveSig.SampleInterval * frag.DecimationFactor; } //添加后段概略点 if (tailCount > 1) { ICursor<T> tailCursor = await myStorageEngine.GetCursorAsync<T>(waveSig.Id, new List<long> { 0 }, new List<long> { tailCount }, new List<long> { headtailDecimationFactor }); x = frag.End; foreach (var data in await tailCursor.Read(tailCursor.LeftPoint)) { points.Add(new SignalPoint<T>(x, data)); x += waveSig.SampleInterval * headtailDecimationFactor; } } return points; } else { return resultArray; } }