LoadingBalanceService.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. using Dapper;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Configuration;
  5. using System.Data;
  6. using System.Data.SqlClient;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. namespace EVCB_OCPP.WSServer.Service
  11. {
  12. public class LoadBalanceSetting
  13. {
  14. public int StationId { set; get; }
  15. public int LBMode { set; get; }
  16. public int LBCurrent { set; get; }
  17. }
  18. public class LoadingBalanceService
  19. {
  20. string mainConnectionString = ConfigurationManager.ConnectionStrings["MainDBContext"].ConnectionString;
  21. string webConnectionString = ConfigurationManager.ConnectionStrings["WebDBContext"].ConnectionString;
  22. public LoadingBalanceService()
  23. {
  24. }
  25. public int GetStationIdByMachineId(string machineId)
  26. {
  27. int stationId = 0;
  28. using (SqlConnection conn = new SqlConnection(webConnectionString))
  29. {
  30. var parameters = new DynamicParameters();
  31. parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
  32. string strSql = "Select StationId from [dbo].[StationMachine] where MachineId=@MachineId ; ";
  33. stationId = conn.ExecuteScalar<Int32>(strSql, parameters);
  34. }
  35. return stationId;
  36. }
  37. public bool IsNeedtoCancelSetting(int stationId, string machineId, string chargeBoxId)
  38. {
  39. var setting = GetLoadBalance(stationId);
  40. if (setting == null) return false;
  41. if (setting.LBMode > 0 && setting.LBMode < 3 && !IsStillInTransactions(chargeBoxId))
  42. {
  43. // renew table
  44. UpdateLoadbalanceRecord(stationId, machineId, 0, DateTime.UtcNow);
  45. return true;
  46. }
  47. if (setting.LBMode >= 3 || setting.LBMode < 1)
  48. {
  49. CloseLoadbalanceRecord(stationId);
  50. }
  51. return false;
  52. }
  53. private void CloseLoadbalanceRecord(int stationId)
  54. {
  55. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  56. {
  57. var parameters = new DynamicParameters();
  58. parameters.Add("@StationId", stationId, DbType.Int32, ParameterDirection.Input);
  59. parameters.Add("@FinishedOn", DateTime.UtcNow, DbType.DateTime, ParameterDirection.Input);
  60. string strSql = "Update [dbo].[LoadingBalance] SET FinishedOn=@FinishedOn where StationId=@StationId and FinishedOn='1991/01/01'; ";
  61. conn.Execute(strSql, parameters);
  62. }
  63. }
  64. private void UpdateLoadbalanceRecord(int stationId, string machineId, decimal power, DateTime? finishedOn, bool keepgoing = false)
  65. {
  66. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  67. {
  68. if (finishedOn.HasValue)
  69. {
  70. var parameters = new DynamicParameters();
  71. parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
  72. parameters.Add("@FinishedOn", finishedOn.Value, DbType.DateTime, ParameterDirection.Input);
  73. string strSql = "Update [dbo].[LoadingBalance] SET FinishedOn=@FinishedOn where MachineId=@MachineId and FinishedOn='1991/01/01'; ";
  74. conn.Execute(strSql, parameters);
  75. }
  76. else
  77. {
  78. if (keepgoing)
  79. {
  80. var parameters = new DynamicParameters();
  81. parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
  82. parameters.Add("@Power", power, DbType.Decimal, ParameterDirection.Input);
  83. string strSql = "Update [dbo].[LoadingBalance] SET Power=@Power where MachineId=@MachineId and FinishedOn='1991/01/01'; ";
  84. conn.Execute(strSql, parameters);
  85. }
  86. else
  87. {
  88. var parameters = new DynamicParameters();
  89. parameters.Add("@StationId", stationId, DbType.Int32, ParameterDirection.Input);
  90. parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
  91. parameters.Add("@Power", power, DbType.Decimal, ParameterDirection.Input);
  92. parameters.Add("@CreatedOn", DateTime.UtcNow, DbType.DateTime, ParameterDirection.Input);
  93. parameters.Add("@FinishedOn", new DateTime(1991, 1, 1, 0, 0, 0, DateTimeKind.Utc), DbType.DateTime, ParameterDirection.Input);
  94. string strSql = "INSERT INTO [dbo].[LoadingBalance] " +
  95. "([StationId],[MachineId],[Power],[CreatedOn],[FinishedOn]) " +
  96. "VALUES(@StationId,@MachineId,@Power,@CreatedOn,@FinishedOn);";
  97. conn.Execute(strSql, parameters);
  98. }
  99. }
  100. }
  101. }
  102. private bool IsStillInTransactions(string chargeBoxId)
  103. {
  104. bool result = false;
  105. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  106. {
  107. var parameters = new DynamicParameters();
  108. parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
  109. string strSql = "Select count(*) from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and StopTime='1991/01/01'; ";
  110. result = conn.ExecuteScalar<bool>(strSql, parameters);
  111. }
  112. return result;
  113. }
  114. private decimal? GetCurrentSetting(string machineId)
  115. {
  116. decimal? result = (decimal?)null;
  117. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  118. {
  119. var parameters = new DynamicParameters();
  120. parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
  121. string strSql = "Select Power from [dbo].[LoadingBalance] where MachineId=@MachineId and FinishedOn='1991/01/01'; ";
  122. result = conn.ExecuteScalar<decimal>(strSql, parameters);
  123. }
  124. return result;
  125. }
  126. public Dictionary<string, decimal?> GetRerangeSettingPower(int stationId)
  127. {
  128. Dictionary<string, decimal?> dic = new Dictionary<string, decimal?>();
  129. var setting = GetLoadBalance(stationId);
  130. if (setting == null) return null;
  131. if (setting != null && setting.LBMode == 2)
  132. {
  133. string machineId = string.Empty;
  134. decimal ratedPower = GetRatedPower(machineId);
  135. //找站內最早要充電的交易 下發充電Power & 填寫新給的Power
  136. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  137. {
  138. var parameters = new DynamicParameters();
  139. parameters.Add("@StationId", stationId, DbType.Int32, ParameterDirection.Input);
  140. string strSql = "Select M.Id from [dbo].[LoadingBalance] LB, [dbo].[Machine] M where LB.StationId=@StationId and LB.MachineId=M.Id and LB.Power < M.RatedPower and LB.FinishedOn='1991/01/01' order by LB.Id asc; ";
  141. machineId = conn.ExecuteScalar<string>(strSql, parameters);
  142. }
  143. if (!string.IsNullOrEmpty(machineId))
  144. {
  145. decimal estimatedPwerValue = GetFCFSPower(stationId, machineId, setting.LBCurrent);
  146. // renew table
  147. UpdateLoadbalanceRecord(stationId, machineId, estimatedPwerValue, null, true);
  148. // UpdateLoadbalanceRecord(stationId, machineId, estimatedPwerValue, null);
  149. dic.Add(machineId, estimatedPwerValue);
  150. }
  151. }
  152. if (setting != null && setting.LBMode == 1)
  153. {
  154. dic = GetAveragePower(stationId, setting.LBCurrent);
  155. foreach (var kv in dic)
  156. {
  157. if (kv.Value.HasValue)
  158. {
  159. UpdateLoadbalanceRecord(stationId, kv.Key, 0, DateTime.UtcNow);
  160. UpdateLoadbalanceRecord(stationId, kv.Key, kv.Value.Value, null);
  161. }
  162. }
  163. }
  164. return dic;
  165. }
  166. public Dictionary<string, decimal?> GetSettingPower(int stationId, string machineId)
  167. {
  168. Dictionary<string, decimal?> dic = new Dictionary<string, decimal?>();
  169. var setting = GetLoadBalance(stationId);
  170. if (setting == null) return null;
  171. if (setting != null)
  172. {
  173. if (setting.LBMode == 1)
  174. {
  175. dic = GetAveragePower(stationId, setting.LBCurrent, machineId);
  176. foreach (var kv in dic)
  177. {
  178. if (kv.Value.HasValue)
  179. {
  180. UpdateLoadbalanceRecord(stationId, kv.Key, 0, DateTime.UtcNow);
  181. UpdateLoadbalanceRecord(stationId, kv.Key, kv.Value.Value, null);
  182. }
  183. }
  184. }
  185. else if (setting.LBMode == 2)
  186. {
  187. dic.Add(machineId, GetFCFSPower(stationId, machineId, setting.LBCurrent));
  188. UpdateLoadbalanceRecord(stationId, machineId, 0, DateTime.UtcNow);
  189. UpdateLoadbalanceRecord(stationId, machineId, dic[machineId].Value, null);
  190. }
  191. else
  192. {
  193. // 把LB TABLE 關閉
  194. CloseLoadbalanceRecord(stationId);
  195. }
  196. }
  197. return dic;
  198. }
  199. public LoadBalanceSetting GetLoadBalance(int stationId)
  200. {
  201. LoadBalanceSetting setting = null;
  202. using (SqlConnection conn = new SqlConnection(webConnectionString))
  203. {
  204. var parameters = new DynamicParameters();
  205. parameters.Add("@StationId", stationId, DbType.Int32, ParameterDirection.Input);
  206. string strSql = "Select LBMode,LBCurrent from [dbo].[Station] where Id=@StationId ; ";
  207. setting = conn.Query<LoadBalanceSetting>(strSql, parameters).FirstOrDefault();
  208. }
  209. return setting;
  210. }
  211. private List<string> GetIdsbyStationId(int stationId)
  212. {
  213. List<string> machineIds = new List<string>();
  214. using (SqlConnection conn = new SqlConnection(webConnectionString))
  215. {
  216. var parameters = new DynamicParameters();
  217. parameters.Add("@StationId", stationId, DbType.Int16, ParameterDirection.Input);
  218. string strSql = "Select MachineId from [dbo].[StationMachine] where StationId=@StationId; ";
  219. machineIds = conn.Query<String>(strSql, parameters).ToList();
  220. }
  221. return machineIds;
  222. }
  223. private Dictionary<string, decimal?> GetAveragePower(int stationId, int availableCapacity, string machineId = "")
  224. {
  225. Dictionary<string, decimal?> dic = new Dictionary<string, decimal?>();
  226. //總量 * 該樁的額定功率/該站充電中樁的總額定功率
  227. List<string> _MachineIds = new List<string>();
  228. int skipCount = 0;
  229. int size = 200;
  230. int takeCount = 0;
  231. int totalRatePower = 0;
  232. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  233. {
  234. var parameters = new DynamicParameters();
  235. parameters.Add("@StationId", stationId, DbType.Int32, ParameterDirection.Input);
  236. string strSql = "Select MachineId from [dbo].[LoadingBalance] where StationId=@StationId and FinishedOn='1991/01/01'; ";
  237. _MachineIds = conn.Query<string>(strSql, parameters).ToList();
  238. }
  239. if (!string.IsNullOrEmpty(machineId) && !_MachineIds.Contains(machineId))
  240. {
  241. _MachineIds.Add(machineId);
  242. }
  243. while (skipCount < _MachineIds.Count())
  244. {
  245. takeCount = _MachineIds.Count() - skipCount > size ? size : _MachineIds.Count() - skipCount;
  246. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  247. {
  248. string strSql = "Select Sum(RatedPower) from [dbo].[Machine] where Id in @machineIds and [Online]=1; ";
  249. totalRatePower += conn.ExecuteScalar<Int32>(strSql, new { machineIds = _MachineIds.ToArray() });
  250. skipCount += takeCount;
  251. }
  252. }
  253. foreach (var id in _MachineIds)
  254. {
  255. int singleRatePower = (int)GetRatedPower(id);
  256. var value = totalRatePower == 0 ? 0 : availableCapacity * singleRatePower / totalRatePower;
  257. dic.Add(id, value);
  258. }
  259. return dic;
  260. }
  261. private decimal GetRatedPower(string machineId)
  262. {
  263. decimal ratedPower = 0;
  264. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  265. {
  266. var parameters = new DynamicParameters();
  267. parameters.Add("@machineId", machineId, DbType.String, ParameterDirection.Input);
  268. string strSql = "Select RatedPower from [dbo].[Machine] where Id=@machineId; ";
  269. ratedPower = conn.ExecuteScalar<Int32>(strSql, parameters);
  270. }
  271. return ratedPower;
  272. }
  273. private decimal GetFCFSPower(int stationId, string machineId, int availableCapacity)
  274. {
  275. decimal ongoingPower = 0;
  276. decimal singleRatePower = GetRatedPower(machineId);
  277. //先找LB 裡面目前下發的Power
  278. decimal? currentPower = GetCurrentSetting(machineId);
  279. if (!currentPower.HasValue) currentPower = 0;
  280. //總量 - 所有正在進行的Power
  281. using (SqlConnection conn = new SqlConnection(mainConnectionString))
  282. {
  283. var parameters = new DynamicParameters();
  284. parameters.Add("@StationId", stationId, DbType.Int32, ParameterDirection.Input);
  285. string strSql = "Select Sum(Power) from [dbo].[LoadingBalance] where StationId=@StationId and FinishedOn='1991/01/01'; ";
  286. ongoingPower = conn.ExecuteScalar<Int32>(strSql, parameters);
  287. }
  288. return availableCapacity - (ongoingPower - currentPower.Value) > singleRatePower ? singleRatePower :
  289. (availableCapacity - (ongoingPower - currentPower.Value) > 0 ? availableCapacity - (ongoingPower - currentPower.Value) : 0);
  290. }
  291. }
  292. }