CalcStateSvc.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. using GDNXFD.Data;
  2. using GDNXFD.Data.Model;
  3. using GDNXFD.Data.Repositories;
  4. using GDNXFD.WcfService.RealtimeState.Domain;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Configuration;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using WisdomClient.data;
  12. namespace GDNXFD.WcfService.RealtimeState
  13. {
  14. public class CalcStateSvc
  15. {
  16. //key 风机型号,value 不可复位的报警id集合
  17. Dictionary<string, HashSet<long>> unAbleResetWarningDic = new Dictionary<string, HashSet<long>>();
  18. //最小切入风速 启停计算 根据当前状态和风速 与最小切入风进行比较, 待机状态,大于切入风,则推荐启动,并网状态,小于切入风,则推荐停机
  19. public Dictionary<string, double> inputSpeedDic;
  20. // 配置文件的风速(低于这个值则表示接近于无风)
  21. double thereIsNoWind = Convert.ToDouble(ConfigurationManager.AppSettings["ThereIsNoWind"]);
  22. // 配置文件的风速(高于这个值则表示接近于有风,扇叶能够转起来)
  23. double theWindIsComing = Convert.ToDouble(ConfigurationManager.AppSettings["TheWindIsComing"]);
  24. //
  25. double thereIsSuperWind=Convert.ToDouble(ConfigurationManager.AppSettings["ThereIsSuperWind"]);
  26. //
  27. double thereIsAlmostNoWind = Convert.ToDouble(ConfigurationManager.AppSettings["ThereIsAlmostNoWind"]);
  28. //
  29. double thereIsAlmostNoPower = Convert.ToDouble(ConfigurationManager.AppSettings["ThereIsAlmostNoPower"]);
  30. //
  31. double maintainLowTemperature = Convert.ToDouble(ConfigurationManager.AppSettings["MaintainLowTemperature"]);
  32. //
  33. double unMaintainLowTemperature = Convert.ToDouble(ConfigurationManager.AppSettings["UnMaintainLowTemperature"]);
  34. #region 单例模式
  35. private CalcStateSvc()
  36. {
  37. }
  38. public static CalcStateSvc Instance
  39. {
  40. get { return SingletonCreator.instance; }
  41. }
  42. class SingletonCreator
  43. {
  44. internal static readonly CalcStateSvc instance = new CalcStateSvc();
  45. }
  46. #endregion
  47. private void createWarningDictionary()
  48. {
  49. if (unAbleResetWarningDic.Count <= 0)
  50. {
  51. try
  52. {
  53. var lst = FaultSnapRepository.getUnabledResetWarning();
  54. if (lst != null && lst.Count > 0)
  55. {
  56. foreach (Warning warn in lst)
  57. {
  58. string key = warn.ModelId;
  59. long value = warn.EDnaValue;
  60. if (unAbleResetWarningDic.ContainsKey(key))
  61. {
  62. HashSet<long> vals = unAbleResetWarningDic[key];
  63. if (vals.Contains(value) == false)
  64. vals.Add(value);
  65. }
  66. else
  67. {
  68. HashSet<long> vals = new HashSet<long>();
  69. vals.Add(value);
  70. unAbleResetWarningDic.Add(key, vals);
  71. }
  72. }
  73. }
  74. }
  75. catch { }
  76. }
  77. }
  78. WStatus[] windturbineRunStatueArray = { WStatus.Online, WStatus.OnPower, WStatus.Start };
  79. public void CalcWindturbine()
  80. {
  81. if (unAbleResetWarningDic.Count <= 0)
  82. createWarningDictionary();
  83. IList<AdviceModel> resetList = new List<AdviceModel>();
  84. IList<AdviceModel> stopList = new List<AdviceModel>();
  85. IList<AdviceModel> startList = new List<AdviceModel>();
  86. #region 计算需要复位的风机
  87. using (GDNXFDDbContext ctx = new GDNXFDDbContext())
  88. {
  89. IList<string> faultWindturbineIdList = ctx.FaultSnap.Where(s => s.Category1 == "FJ" && s.IsOpened == true && s.StationId.Contains("_FDC") && !s.StationId.Contains("QS")).ToList().Select(s => s.WindturbineId).ToList();
  90. DateTime time = DateTime.Now.AddDays(-3);
  91. IList<AlertSnap> alertSnap = ctx.AlertSnap.Where(s => faultWindturbineIdList.Contains(s.WindturbineId) && s.Category1 == "windturbine" && s.IsOpened == true && s.LastUpdateTime > time).ToList();
  92. for (int i = 0; i < alertSnap.Count; i++)
  93. {
  94. bool allowReset = true;
  95. if(alertSnap[i].ModelId.IndexOf("105")>0)
  96. {
  97. continue;
  98. }
  99. //unAbleResetWarningDic 只包含1.5MW机型,若报警风机为2MW则默认风机可以进行复位
  100. if (unAbleResetWarningDic.ContainsKey(alertSnap[i].ModelId))
  101. {
  102. HashSet<long> vals = unAbleResetWarningDic[alertSnap[i].ModelId];
  103. if (vals != null && vals.Count > 0 && vals.Contains(alertSnap[i].AlertValue))
  104. {
  105. allowReset = false;
  106. }
  107. if (allowReset)
  108. {
  109. AdviceModel m = new AdviceModel();
  110. m.WindturbineId = alertSnap[i].WindturbineId;
  111. m.StationId = alertSnap[i].StationId;
  112. m.ModelId = alertSnap[i].ModelId;
  113. m.AdviseOperation = OperateStyle.Reset;
  114. m.AdviceType = CalculationOriginType.Alarm;
  115. m.LastUpdateTime = DateTime.Now;
  116. m.Status = 1;
  117. resetList.Add(m);
  118. }
  119. }
  120. else
  121. {
  122. AdviceModel m = new AdviceModel();
  123. m.WindturbineId = alertSnap[i].WindturbineId;
  124. m.StationId = alertSnap[i].StationId;
  125. m.ModelId = alertSnap[i].ModelId;
  126. m.AdviseOperation = OperateStyle.Reset;
  127. m.AdviceType = CalculationOriginType.Alarm;
  128. m.LastUpdateTime = DateTime.Now;
  129. m.Status = 1;
  130. resetList.Add(m);
  131. }
  132. }
  133. }
  134. #endregion
  135. if (inputSpeedDic == null || inputSpeedDic.Count <= 0)
  136. GetWindturbineInputWindSpeed();
  137. D("==============================");
  138. D("======启停推荐(10.15)======");
  139. D("==============================");
  140. //WXW
  141. #region 计算需要启停的风机2.0
  142. List<string> resetWindturbine = resetList.Select(s => s.WindturbineId).ToList();
  143. #region 风机启动推荐算法
  144. /*
  145. * 推荐启动逻辑:
  146. * 当风机没有被复位,
  147. * 且风机正在待机,
  148. * 且没有被挂牌操作,
  149. * 现场没有人员在风机上(就地维护),
  150. * 风资源良好(当前风速达到启动风速,并且5分钟的平均风速良好),
  151. * 且风机不是大风天,则推荐风机启动)
  152. */
  153. var startSuggest = AdviceCache.Instance.dicWindturbineInfo.Where(w =>
  154. !resetWindturbine.Contains(w.Key)&& // 非复位
  155. w.Value.StatusCode.TagData.doubleValue.HasValue && w.Value.StatusCode.TagData.doubleValue.Value== (int)WStatus.Standby && // 待机中
  156. w.Value.LockCode.TagData.doubleValue.HasValue && w.Value.LockCode.TagData.doubleValue.Value == (int)HungType.UnLock && //未挂牌
  157. inputSpeedDic.ContainsKey(w.Key)&&
  158. w.Value.WindSpeedCode.TagData.doubleValue.HasValue && w.Value.WindSpeedCode.TagData.doubleValue.Value > inputSpeedDic[w.Key] &&// 当前风速好
  159. w.Value.WindSpeedCode.TagData.doubleValue.Value < thereIsSuperWind && // 不是超级大风天
  160. w.Value.WindSpeedCodeFiveMin.TagData.doubleValue.HasValue && w.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value > inputSpeedDic[w.Key]//5分钟的风速好
  161. );
  162. foreach (var kv in startSuggest)
  163. {
  164. AdviceModel m = new AdviceModel();
  165. m.WindturbineId = kv.Value.WindturbineId;
  166. m.StationId = kv.Value.Windturbine.WindPowerStationId;
  167. m.ModelId = kv.Value.Windturbine.ModelId;
  168. m.AdviseOperation = OperateStyle.Start;
  169. m.AdviceType = CalculationOriginType.RealTimeStatus;
  170. m.LastUpdateTime = DateTime.Now;
  171. m.AdviceExecuteTime = DateTime.Now;
  172. m.Status = 1;
  173. startList.Add(m);
  174. D("Start=====>"+m.WindturbineId+"\t"+kv.Value.WindSpeedCode.TagData.doubleValue.Value.ToString("f2")+"\t\t\t\t\t----------->启动");
  175. }
  176. #endregion
  177. #region 风机停机推荐算法
  178. // 此处没有添加针对台风模式和冰冻模式的算法
  179. /*
  180. * 台风模式:一般当风大于约25m/s(各机型不一样)的切出风速,风机就会停机,桨叶收起,然后对风偏航,这在海上比较重要
  181. *
  182. * 冰冻模式:当风速和功率比值不对,并且气温在±5℃,湿度在某值时,桨叶可能有结冰现象,此时也应该推荐停机
  183. *
  184. * 以下实现的算法:
  185. * 在风机没有被复位,而且正在运行,也没有挂牌时,风速渐小(5分钟的平均风速小于切入风速),当前风速小于切入风,风机产生的功率某值(0),表示风机发电条件已经很不满足,则推荐风机停机
  186. */
  187. var stopSuggest = AdviceCache.Instance.dicWindturbineInfo.Where(t =>
  188. !resetWindturbine.Contains(t.Key) && // 非复位
  189. // 正在运行
  190. t.Value.StatusCode.TagData.doubleValue.HasValue && windturbineRunStatueArray.Contains(HelpperMethod.GetWindturbineStatus(t.Value.StatusCode.TagData.doubleValue.Value)) &&
  191. t.Value.LockCode.TagData.doubleValue.HasValue && t.Value.LockCode.TagData.doubleValue.Value == (int)HungType.UnLock && //未挂牌
  192. t.Value.WindSpeedCode.TagData.doubleValue.HasValue && t.Value.WindSpeedCode.TagData.doubleValue.Value < thereIsAlmostNoWind && // 当前风不好了
  193. t.Value.WindSpeedCodeFiveMin.TagData.doubleValue.HasValue && t.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value < thereIsAlmostNoWind &&//5分钟的风速也不好
  194. t.Value.WindturbinePower.TagData.doubleValue.HasValue && t.Value.WindturbinePower.TagData.doubleValue.Value< thereIsAlmostNoPower //功率小于某个值
  195. );
  196. foreach (var kv in stopSuggest)
  197. {
  198. AdviceModel m = new AdviceModel();
  199. m.WindturbineId = kv.Value.WindturbineId;
  200. m.StationId = kv.Value.Windturbine.WindPowerStationId;
  201. m.ModelId = kv.Value.Windturbine.ModelId;
  202. m.AdviseOperation = OperateStyle.Start;
  203. m.AdviceType = CalculationOriginType.RealTimeStatus;
  204. m.LastUpdateTime = DateTime.Now;
  205. m.AdviceExecuteTime = DateTime.Now;
  206. m.Status = 1;
  207. stopList.Add(m);
  208. D("Stop =====>" + m.WindturbineId + "\t" + kv.Value.WindSpeedCode.TagData.doubleValue.Value.ToString("f2") + "\t=====================>停机[" + kv.Value.WindturbinePower.TagData.doubleValue.Value.ToString("f2")+"kW.h]");
  209. }
  210. #endregion
  211. #endregion
  212. #region 2019/10/15前的推荐算法(弃用) 计算需要启停的风机
  213. //IList <string> resetWindturbineIdList = resetList.Select(s => s.WindturbineId).ToList();
  214. ////排除需要复位的风机
  215. //IList<string> calcWindturbineKeyList = AdviceCache.Instance.dicWindturbineInfo.Keys.ToList();
  216. //for (int i = 0; i < calcWindturbineKeyList.Count; i++)
  217. //{
  218. // WindturbineInfo info = AdviceCache.Instance.dicWindturbineInfo[calcWindturbineKeyList[i]];
  219. // // 排除需要复位的风机
  220. // if (!resetWindturbineIdList.Contains(calcWindturbineKeyList[i]))
  221. // {
  222. // WStatus? st = null;
  223. // HungType? hungType = null;
  224. // double? windSpeed = null;
  225. // if (info.StatusCode.TagData.doubleValue.HasValue)
  226. // st = HelpperMethod.GetWindturbineStatus(info.StatusCode.TagData.doubleValue.Value);
  227. // if (info.LockCode.TagData.doubleValue.HasValue)
  228. // hungType = HelpperMethod.GetHungType(info.LockCode.TagData.doubleValue.Value);
  229. // if (info.WindSpeedCode.TagData.doubleValue.HasValue)
  230. // windSpeed = info.WindSpeedCode.TagData.doubleValue.Value;
  231. // if (!inputSpeedDic.ContainsKey(info.WindturbineId))
  232. // continue;
  233. // //获取切入风
  234. // double putSpeed = inputSpeedDic[info.WindturbineId];
  235. // WStatus[] allowStopStatusArr = { WStatus.Online, WStatus.OnPower, WStatus.Start };
  236. // //如果风机状态不为空,风速不为空,且未挂牌
  237. // if (st.HasValue && hungType.HasValue && windSpeed.HasValue && hungType.Value == HungType.UnLock)
  238. // {
  239. // //如果风机当前状态为待机
  240. // if (st == WStatus.Standby)
  241. // {
  242. // //如果当前风速大于风机的切入风速,则推荐启动,否则不做任何操作
  243. // if (windSpeed.HasValue && windSpeed >= 3.5 )
  244. // {
  245. // AdviceModel m = new AdviceModel();
  246. // m.WindturbineId = info.WindturbineId;
  247. // m.StationId = info.Windturbine.WindPowerStationId;
  248. // m.ModelId = info.Windturbine.ModelId;
  249. // m.AdviseOperation = OperateStyle.Start;
  250. // m.AdviceType = CalculationOriginType.RealTimeStatus;
  251. // m.LastUpdateTime = DateTime.Now;
  252. // m.AdviceExecuteTime = DateTime.Now;
  253. // m.Status = 1;
  254. // stopList.Add(m);
  255. // }
  256. // }
  257. // //如果当前风机状态是并网状态,启动状态,上电状态,
  258. // else if (WStatus.Online==st.Value)
  259. // {
  260. // //如果当前风小于切入风
  261. // if (windSpeed < 3.0)
  262. // {
  263. // AdviceModel m = new AdviceModel();
  264. // m.WindturbineId = info.WindturbineId;
  265. // m.StationId = info.Windturbine.WindPowerStationId;
  266. // m.ModelId = info.Windturbine.ModelId;
  267. // m.AdviseOperation = OperateStyle.Stop;
  268. // m.AdviceType = CalculationOriginType.RealTimeStatus;
  269. // m.LastUpdateTime = DateTime.Now;
  270. // m.AdviceExecuteTime = DateTime.Now;
  271. // m.Status = 1;
  272. // startList.Add(m);
  273. // }
  274. // }
  275. // }
  276. // }
  277. //}
  278. #endregion
  279. //Console.WriteLine("风机实时推荐计算完毕");
  280. IList<AdviceModel> finalResultList = resetList.Union(stopList).Union(startList).ToList();
  281. //将最终结果添加到结果缓存中
  282. AdviceCache.Instance.AdviceListAdd(finalResultList);
  283. }
  284. /// <summary>
  285. /// 全场无风,推荐待机状态的风机打维护(减少耗电) 或者 全场有风,风的条件比较好,将维护状态下的风机推荐为取消维护
  286. /// </summary>
  287. public void TryMaintainWindturbine()
  288. {
  289. try
  290. {
  291. IList<AdviceModel> maintainList = new List<AdviceModel>();
  292. Dictionary<string, WindturbineInfo> windDictionary = AdviceCache.Instance.dicWindturbineInfo;
  293. // 利用场站分组
  294. var stationGroup = windDictionary.GroupBy(x => x.Value.Windturbine.WindPowerStationId);
  295. D("==============================");
  296. D("======维护推荐(10.15)======");
  297. D("==============================");
  298. // 针对各个场站计算出一个平均风速.针对每个期计算出平均风速
  299. foreach (var item in stationGroup) //(Grouping<string, Dictionary<string, WindturbineInfo>> item in stationGroup)
  300. {
  301. string stationName = item.Key;
  302. // 全场站的5分钟平均风速
  303. var stationAverage = item.Where(w=>w.Value.StatusCode.TagData.doubleValue.Value!= (int)WStatus.Offline).Select(s => s.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value).Average();//(k => k.Select(m => m.WindSpeedCode.TagData.doubleValue.Value).ToList().Average());//item.Select(s => s.Values)//.Select(w => w.WindSpeedCode.TagData.longValue).Average());
  304. var maxV = item.Where(w => w.Value.StatusCode.TagData.doubleValue.Value != (int)WStatus.Offline).Select(s => s.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value).Max();
  305. var minV = item.Where(w => w.Value.StatusCode.TagData.doubleValue.Value != (int)WStatus.Offline).Select(s => s.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value).Min();
  306. //D("[+]场站:" + stationName.PadRight(24) + "\t" + "最高值:" + maxV.ToString("0.000").PadRight(20) + "\t" + "最低值:" + minV.ToString("0.000").PadRight(20) + "\t" + "平均值:" + stationAverage.ToString("0.000"));
  307. // 按照项目5分钟平均风速 分组
  308. var projectGroup = item.GroupBy(p => p.Value.Windturbine.ProjectId);
  309. foreach (var project in projectGroup)
  310. {
  311. string projectName = project.Key;
  312. var projectAverage = project.Select(a => a.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value).Average();
  313. var pMax = project.Where(w => w.Value.StatusCode.TagData.doubleValue.Value != (int)WStatus.Offline).Select(a => a.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value).Max();
  314. var pMin = project.Where(w => w.Value.StatusCode.TagData.doubleValue.Value != (int)WStatus.Offline).Select(a => a.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value).Min();
  315. //D("[+]项目 :" + projectName.PadRight(16) + "最高值:" + pMax.ToString("0.000").PadRight(20) + "\t" + "最低值:" + pMin.ToString("0.000").PadRight(20) + "\t" + "平均值:" + projectAverage.ToString("0.000"));
  316. // 当前项目的平均风速
  317. var projectCurrentAverage = project.Where(w => w.Value.StatusCode.TagData.doubleValue.Value != (int)WStatus.Offline).Select(a => a.Value.WindSpeedCode.TagData.doubleValue.Value).Average();
  318. var currentMax = project.Where(w => w.Value.StatusCode.TagData.doubleValue.Value != (int)WStatus.Offline).Select(a => a.Value.WindSpeedCode.TagData.doubleValue.Value).Max();
  319. var currentMin = project.Where(w => w.Value.StatusCode.TagData.doubleValue.Value != (int)WStatus.Offline).Select(a => a.Value.WindSpeedCode.TagData.doubleValue.Value).Min();
  320. //D("[+]项目当前:" + projectName.PadRight(16) + "最高值:" + currentMax.ToString("0.000").PadRight(20) + "\t" + "最低值:" + currentMin.ToString("0.000").PadRight(20) + "\t" + "平均值:" + projectCurrentAverage.ToString("0.000"));
  321. if (thereIsNoWind > projectCurrentAverage && thereIsNoWind > stationAverage)// && thereIsNoWind > currentMax)
  322. {
  323. // 项目中 如果最大的风速还是比我们预定的风速还小,证明整个项目区域的风速就比较小 满足全场无风了
  324. #region 推荐维护
  325. /*
  326. * 风机维护推荐算法:
  327. *
  328. * 风机没有被挂牌
  329. * 风机在待机状态
  330. * 5分钟平均风速小于2.7m/s
  331. * 风机本身风速小于2.7m/s
  332. * 机舱温度大于0℃
  333. *
  334. **/
  335. var turbineDictionary = project.Where(w =>
  336. !w.Value.Windturbine.ModelId.Contains("UP105") &&
  337. w.Value.LockCode.TagData.doubleValue.Value == (int)HungType.UnLock &&
  338. HelpperMethod.GetWindturbineStatus(w.Value.StatusCode.TagData.doubleValue.Value) == WStatus.Standby &&
  339. w.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value < thereIsNoWind &&
  340. w.Value.WindSpeedCode.TagData.doubleValue.Value < thereIsNoWind &&
  341. w.Value.BoxTemperature.TagData.doubleValue > maintainLowTemperature //冬天的时候就不推荐全场无风了,需要保持偏航和内部设备运转
  342. );
  343. foreach (var kv in turbineDictionary)
  344. {
  345. D("[+]:风机:" + kv.Value.WindturbineId + "\t风速" + kv.Value.WindSpeedCode.TagData.doubleValue.Value.ToString("0.0000") + "\t----->推荐打维护");
  346. AdviceModel m = new AdviceModel();
  347. m.WindturbineId = kv.Value.WindturbineId;
  348. m.StationId = kv.Value.Windturbine.WindPowerStationId;
  349. m.ModelId = kv.Value.Windturbine.ModelId;
  350. m.AdviseOperation = OperateStyle.Maintain;// 建议维护
  351. m.AdviceType = CalculationOriginType.RealTimeStatus; // 实时状态
  352. m.LastUpdateTime = DateTime.Now;
  353. m.AdviceExecuteTime = DateTime.Now;
  354. m.Status = 1;
  355. maintainList.Add(m);
  356. }
  357. #endregion
  358. }
  359. else if (projectCurrentAverage > theWindIsComing && stationAverage > theWindIsComing)
  360. {
  361. // 当前项目和场站的平均风速都达到了很好的有风条件,则满足全场有风
  362. #region 推荐取消维护
  363. /*
  364. * 取消维护推荐算法:
  365. *
  366. * 风机没有挂牌
  367. * 风机正在维护状态
  368. * 风机的5分钟平均风速良好
  369. *
  370. * 或者
  371. *
  372. * 风机没有挂牌
  373. * 风机正在 维护状态
  374. * 风机的机舱温度太低(-10℃)
  375. */
  376. var turbineDictionary = project.Where(w =>
  377. (
  378. !w.Value.Windturbine.ModelId.Contains("UP105") &&
  379. w.Value.LockCode.TagData.doubleValue.Value == (int)HungType.UnLock &&
  380. HelpperMethod.GetWindturbineStatus(w.Value.StatusCode.TagData.doubleValue.Value) == WStatus.Maintain &&
  381. w.Value.WindSpeedCodeFiveMin.TagData.doubleValue.Value > theWindIsComing &&
  382. w.Value.WindSpeedCode.TagData.doubleValue.Value > theWindIsComing
  383. )
  384. ||
  385. (// 维护时机舱温度过低,推荐取消维护
  386. !w.Value.Windturbine.ModelId.Contains("UP105") &&
  387. w.Value.LockCode.TagData.doubleValue.Value == (int)HungType.UnLock &&
  388. HelpperMethod.GetWindturbineStatus(w.Value.StatusCode.TagData.doubleValue.Value) == WStatus.Maintain &&
  389. w.Value.BoxTemperature.TagData.doubleValue < unMaintainLowTemperature
  390. )
  391. );
  392. foreach (var kv in turbineDictionary)
  393. {
  394. D("[+]:风机:" + kv.Value.WindturbineId + "\t风速" + kv.Value.WindSpeedCode.TagData.doubleValue.Value.ToString("0.0000") + "\t----->推荐取消维护["+kv.Value.BoxTemperature.TagData.doubleValue.Value.ToString("f2")+"℃]");
  395. AdviceModel m = new AdviceModel();
  396. m.WindturbineId = kv.Value.WindturbineId;
  397. m.StationId = kv.Value.Windturbine.WindPowerStationId;
  398. m.ModelId = kv.Value.Windturbine.ModelId;
  399. m.AdviseOperation = OperateStyle.UnMaintain;//建议取消维护
  400. m.AdviceType = CalculationOriginType.RealTimeStatus; // 实时状态
  401. m.LastUpdateTime = DateTime.Now;
  402. m.AdviceExecuteTime = DateTime.Now;
  403. m.Status = 1;
  404. maintainList.Add(m);
  405. }
  406. #endregion
  407. }
  408. }
  409. }
  410. D("==============================>");
  411. //将最终结果添加到结果缓存中
  412. AdviceCache.Instance.AddMaintainAdvice(maintainList);
  413. }
  414. catch (Exception e)
  415. {
  416. D(e.ToString());
  417. }
  418. }
  419. bool allowDebug = ConfigurationManager.AppSettings["AllowDebug"].ToUpper() == "Y";
  420. bool allowPrint = ConfigurationManager.AppSettings["AllowPrint"].ToUpper() == "Y";
  421. private void D(string debugText)
  422. {
  423. try
  424. {
  425. if (allowDebug)
  426. {
  427. System.Diagnostics.Debug.WriteLine(debugText);
  428. }
  429. if (allowPrint)
  430. {
  431. Console.WriteLine(debugText);
  432. }
  433. }
  434. catch (Exception ex)
  435. {
  436. //logger.Info(ex.Message);
  437. System.Diagnostics.Debug.WriteLine(ex.ToString());
  438. }
  439. }
  440. public void GetWindturbineInputWindSpeed()
  441. {
  442. if (inputSpeedDic == null)
  443. inputSpeedDic = new Dictionary<string, double>();
  444. using (GDNXFDDbContext ctx = new GDNXFDDbContext())
  445. {
  446. string sql = @"select id, windturbineid, recorddate, inputsmall from inputoroutputspeedtotal t where t.recorddate = (select max(recorddate) from inputoroutputspeedtotal)";
  447. IList<InputOrOutputSpeedTotal> speedTotalList = ctx.InputOrOutputSpeedTotal.SqlQuery(sql, new object[] { }).ToList();
  448. for (int i = 0; i < speedTotalList.Count; i++)
  449. {
  450. if (!inputSpeedDic.ContainsKey(speedTotalList[i].WindturbineId))
  451. inputSpeedDic.Add(speedTotalList[i].WindturbineId, speedTotalList[i].InputSmall);
  452. }
  453. }
  454. }
  455. }
  456. }
  457. /*
  458. private enum FGLTrend
  459. {
  460. Up,
  461. Down,
  462. NoChange
  463. }
  464. private FGLTrend GetFGLYC(string stationID, out double guessMax)
  465. {
  466. try
  467. {
  468. string[] unifmCodes = ConfigurationManager.AppSettings["StationFGLYC"].Split(',');// 配置中的Code使用','分隔
  469. Dictionary<string, TsData> shotestGuess = WisdomClient.RestfulClient.findLatestByThingCodes("station", stationID, unifmCodes);
  470. //if (stationID == "SBQ_FDC")
  471. //{
  472. // guessMax = shotestGuess.Select(s => s.Value.doubleValue.Value).Max();
  473. // string[] unifmCodesSBQB = ConfigurationManager.AppSettings["StationFGLYCSBQ"].Split(',');// 配置中的Code使用','分隔
  474. // Dictionary<string, TsData> shotestGuessSBQB = WisdomClient.RestfulClient.findLatestByThingCodes("station", stationID, unifmCodesSBQB);
  475. // double guessMaxTmp = shotestGuessSBQB.Select(s => s.Value.doubleValue.Value).Max();
  476. // guessMax = guessMax > guessMaxTmp ? guessMaxTmp : guessMaxTmp;//确定峰值的最大
  477. // FGLTrend SQBTrendA = shotestGuess["FCFGCDQ0001"].doubleValue.Value < shotestGuess["FCFGCDQ0016"].doubleValue.Value ? FGLTrend.Up : FGLTrend.Down;
  478. // FGLTrend SQBTrendB = shotestGuessSBQB["FCFGCDQ0001"].doubleValue.Value < shotestGuessSBQB["FCFGCDQ0016"].doubleValue.Value ? FGLTrend.Up : FGLTrend.Down;
  479. // // 同升则升 不升则视为降(风速均匀也视为降)
  480. // return (SQBTrendA == SQBTrendB && SQBTrendB == FGLTrend.Up) ? FGLTrend.Up : FGLTrend.Down;
  481. //}
  482. //else
  483. //{
  484. // FCFGCDQ0001
  485. // FCFGCDQ0016
  486. // 取最近的值和最未来的预测值比较,如果预测风势降低,则返回Down,如果升高则返回UP
  487. // 还要返回最后的预测风速
  488. //
  489. guessMax = shotestGuess.Select(s => s.Value.doubleValue.Value).Max(); // 预测风速中的峰值
  490. return shotestGuess["FCFGCDQ0001"].doubleValue.Value < shotestGuess["FCFGCDQ0016"].doubleValue.Value ? FGLTrend.Up : FGLTrend.Down;
  491. //}
  492. }
  493. catch (Exception e)
  494. {
  495. //System.Diagnostics.Debug.WriteLine(e.ToString());
  496. guessMax = 100;// 返回一个虚拟的大值
  497. return FGLTrend.Up;
  498. }
  499. }
  500. */