CoreProfileHandler.cs 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421
  1. using Dapper;
  2. using EVCB_OCPP.Domain;
  3. using EVCB_OCPP.Domain.Models.Database;
  4. using EVCB_OCPP.Packet.Features;
  5. using EVCB_OCPP.Packet.Messages;
  6. using EVCB_OCPP.Packet.Messages.Core;
  7. using EVCB_OCPP.Packet.Messages.SubTypes;
  8. using EVCB_OCPP.WSServer.Dto;
  9. using EVCB_OCPP.WSServer.Service;
  10. using Newtonsoft.Json;
  11. using NLog;
  12. using OCPPPackage.Profiles;
  13. using OCPPServer.Protocol;
  14. using System;
  15. using System.Collections.Generic;
  16. using System.Configuration;
  17. using System.Data;
  18. using System.Data.Entity;
  19. using System.Data.SqlClient;
  20. using System.Diagnostics;
  21. using System.Globalization;
  22. using System.Linq;
  23. using System.Threading.Tasks;
  24. namespace EVCB_OCPP.WSServer.Message
  25. {
  26. public class ID_CreditDeductResult
  27. {
  28. public int txId { set; get; }
  29. public string creditNo { set; get; }
  30. public bool deductResult { set; get; }
  31. public bool isDonateInvoice { set; get; }
  32. public decimal amount { set; get; }
  33. public string approvalNo { set; get; }
  34. }
  35. internal partial class ProfileHandler
  36. {
  37. static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
  38. string webConnectionString = ConfigurationManager.ConnectionStrings["WebDBContext"].ConnectionString;
  39. private OuterHttpClient httpClient = new OuterHttpClient();
  40. async internal Task<MessageResult> ExecuteCoreRequest(Actions action, ClientData session, IRequest request)
  41. {
  42. Stopwatch watch = new Stopwatch();
  43. if (action == Actions.Heartbeat)
  44. {
  45. watch.Start();
  46. }
  47. MessageResult result = new MessageResult() { Success = false };
  48. try
  49. {
  50. switch (action)
  51. {
  52. case Actions.DataTransfer:
  53. {
  54. DataTransferRequest _request = request as DataTransferRequest;
  55. var creditDeductResult = JsonConvert.DeserializeObject<ID_CreditDeductResult>(_request.data);
  56. var confirm = new DataTransferConfirmation() { status = DataTransferStatus.Accepted };
  57. if (_request.messageId == "ID_CreditDeductResult")
  58. {
  59. if (session.CustomerId == new Guid("009E603C-79CD-4620-A2B8-D9349C0E8AD8"))
  60. {
  61. var report = new
  62. {
  63. ChargeBoxId = session.ChargeBoxId,
  64. IsDonateInvoice = creditDeductResult.isDonateInvoice,
  65. CreditNo = creditDeductResult.creditNo,
  66. DeductResult = creditDeductResult.deductResult,
  67. SessionId = creditDeductResult.txId,
  68. ApprovalNo= creditDeductResult.approvalNo,
  69. TotalCost = creditDeductResult.amount,
  70. };
  71. logger.Debug(string.Format("URL:{0}", GlobalConfig.TCC_API_URL + "prepare_issue_invoice"));
  72. logger.Debug(JsonConvert.SerializeObject(report));
  73. var response = await httpClient.Post(GlobalConfig.TCC_API_URL + "prepare_issue_invoice", new Dictionary<string, string>()
  74. {
  75. { "PartnerId",session.CustomerId.ToString()}
  76. }, report, GlobalConfig.TCC_SALTKEY);
  77. logger.Debug(JsonConvert.SerializeObject(response));
  78. }
  79. confirm.data = JsonConvert.SerializeObject(new { txId = creditDeductResult.txId, creditNo = creditDeductResult.creditNo, msgId = _request.messageId });
  80. }
  81. result.Message = confirm;
  82. result.Success = true;
  83. }
  84. break;
  85. case Actions.BootNotification:
  86. {
  87. BootNotificationRequest _request = request as BootNotificationRequest;
  88. int heartbeat_interval = GlobalConfig.GetHEARTBEAT_INTERVAL();
  89. using (var db = new MainDBContext())
  90. {
  91. var _machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
  92. _machine.ChargeBoxSerialNumber = string.IsNullOrEmpty(_request.chargeBoxSerialNumber) ? string.Empty : _request.chargeBoxSerialNumber;
  93. _machine.ChargePointSerialNumber = string.IsNullOrEmpty(_request.chargePointSerialNumber) ? string.Empty : _request.chargePointSerialNumber;
  94. _machine.ChargePointModel = string.IsNullOrEmpty(_request.chargePointModel) ? string.Empty : _request.chargePointModel;
  95. _machine.ChargePointVendor = string.IsNullOrEmpty(_request.chargePointVendor) ? string.Empty : _request.chargePointVendor;
  96. _machine.FW_CurrentVersion = string.IsNullOrEmpty(_request.firmwareVersion) ? string.Empty : _request.firmwareVersion;
  97. //_machine.Iccid = string.IsNullOrEmpty(_request.iccid) ? string.Empty : _request.iccid;
  98. _machine.Iccid = DateTime.UtcNow.ToString("yy-MM-dd HH:mm");
  99. _machine.Imsi = string.IsNullOrEmpty(_request.imsi) ? string.Empty : _request.imsi;
  100. _machine.MeterSerialNumber = string.IsNullOrEmpty(_request.meterSerialNumber) ? string.Empty : _request.meterSerialNumber;
  101. _machine.MeterType = string.IsNullOrEmpty(_request.meterType) ? string.Empty : _request.meterType;
  102. db.SaveChanges();
  103. var configVaule = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.ConfigureName == StandardConfiguration.HeartbeatInterval)
  104. .Select(x => x.ConfigureSetting).FirstOrDefault();
  105. if (configVaule != null)
  106. {
  107. int.TryParse(configVaule, out heartbeat_interval);
  108. }
  109. }
  110. var confirm = new BootNotificationConfirmation() { currentTime = DateTime.UtcNow, interval = session.IsPending ? heartbeat_interval : 5, status = session.IsPending ? Packet.Messages.SubTypes.RegistrationStatus.Accepted : RegistrationStatus.Pending };
  111. session.IsPending = !session.IsPending;
  112. result.Message = confirm;
  113. result.Success = true;
  114. }
  115. break;
  116. case Actions.StatusNotification:
  117. {
  118. //只保留最新上報狀況
  119. StatusNotificationRequest _request = request as StatusNotificationRequest;
  120. int preStatus = 0;
  121. using (var db = new MainDBContext())
  122. {
  123. var _oldStatus = db.ConnectorStatus.Where(x => x.ChargeBoxId == session.ChargeBoxId
  124. && x.ConnectorId == _request.connectorId).AsNoTracking().FirstOrDefault();
  125. if (_oldStatus != null && (_request.status != (ChargePointStatus)_oldStatus.Status || _request.status == ChargePointStatus.Faulted))
  126. {
  127. preStatus = _oldStatus.Status;
  128. db.Configuration.AutoDetectChangesEnabled = false;
  129. db.Configuration.ValidateOnSaveEnabled = false;
  130. db.ConnectorStatus.Attach(_oldStatus);
  131. _oldStatus.CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.UtcNow;
  132. _oldStatus.Status = (int)_request.status;
  133. _oldStatus.ChargePointErrorCodeId = (int)_request.errorCode;
  134. _oldStatus.ErrorInfo = string.IsNullOrEmpty(_request.info) ? string.Empty : _request.info;
  135. _oldStatus.VendorId = string.IsNullOrEmpty(_request.vendorId) ? string.Empty : _request.vendorId;
  136. _oldStatus.VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode;
  137. db.Entry(_oldStatus).Property(x => x.CreatedOn).IsModified = true;
  138. db.Entry(_oldStatus).Property(x => x.Status).IsModified = true;
  139. db.Entry(_oldStatus).Property(x => x.ChargePointErrorCodeId).IsModified = true;
  140. db.Entry(_oldStatus).Property(x => x.ErrorInfo).IsModified = true;
  141. db.Entry(_oldStatus).Property(x => x.VendorId).IsModified = true;
  142. db.Entry(_oldStatus).Property(x => x.VendorErrorCode).IsModified = true;
  143. }
  144. if (_oldStatus == null)
  145. {
  146. var _currentStatus = new Domain.Models.Database.ConnectorStatus()
  147. {
  148. ChargeBoxId = session.ChargeBoxId,
  149. ConnectorId = (byte)_request.connectorId,
  150. CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.UtcNow,
  151. Status = (int)_request.status,
  152. ChargePointErrorCodeId = (int)_request.errorCode,
  153. ErrorInfo = string.IsNullOrEmpty(_request.info) ? string.Empty : _request.info,
  154. VendorId = string.IsNullOrEmpty(_request.vendorId) ? string.Empty : _request.vendorId,
  155. VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode,
  156. Id = Guid.NewGuid().ToString()
  157. };
  158. db.ConnectorStatus.Add(_currentStatus);
  159. }
  160. if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
  161. {
  162. db.MachineError.Add(new MachineError()
  163. {
  164. ConnectorId = (byte)_request.connectorId,
  165. CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.UtcNow,
  166. Status = (int)_request.status,
  167. ChargeBoxId = session.ChargeBoxId,
  168. ErrorCodeId = (int)_request.errorCode,
  169. ErrorInfo = string.IsNullOrEmpty(_request.info) ? string.Empty : _request.info,
  170. PreStatus = _oldStatus == null ? -1 : preStatus,
  171. VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode,
  172. VendorId = string.IsNullOrEmpty(_request.vendorId) ? string.Empty : _request.vendorId
  173. });
  174. }
  175. db.SaveChanges();
  176. }
  177. if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
  178. {
  179. var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
  180. var notification = businessService.NotifyFaultStatus(new ErrorDetails()
  181. {
  182. ChargeBoxId = session.ChargeBoxId,
  183. ConnectorId = _request.connectorId,
  184. ErrorCode = _request.errorCode,
  185. Info = string.IsNullOrEmpty(_request.info) ? string.Empty : _request.info,
  186. OCcuredOn = _request.timestamp ?? DateTime.UtcNow,
  187. VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode,
  188. });
  189. }
  190. var confirm = new StatusNotificationConfirmation() { };
  191. result.Message = confirm;
  192. result.Success = true;
  193. }
  194. break;
  195. case Actions.Heartbeat:
  196. {
  197. var confirm = new HeartbeatConfirmation() { currentTime = DateTime.UtcNow };
  198. result.Message = confirm;
  199. result.Success = true;
  200. }
  201. break;
  202. case Actions.MeterValues:
  203. {
  204. MeterValuesRequest _request = request as MeterValuesRequest;
  205. decimal energy_kwh = 0;
  206. if (_request.meterValue.Count > 0)
  207. {
  208. using (var db = new MeterValueDBContext())
  209. {
  210. foreach (var item in _request.meterValue)
  211. {
  212. int registerCount = item.sampledValue.Where(x => x.measurand == Measurand.Energy_Active_Import_Interval).ToList().Count;
  213. if (registerCount > 0)
  214. {
  215. registerCount = 0;
  216. }
  217. else
  218. {
  219. registerCount = item.sampledValue.Where(x => x.measurand == Measurand.Energy_Active_Import_Register).ToList().Count;
  220. }
  221. if (registerCount > 0)
  222. {
  223. string voltage_text = item.sampledValue.Where(x => x.measurand == Measurand.Voltage).Select(x => x.value).FirstOrDefault();
  224. decimal voltage = decimal.Parse(voltage_text);
  225. string current_text = item.sampledValue.Where(x => x.measurand == Measurand.Current_Import).Select(x => x.value).FirstOrDefault();
  226. decimal current = decimal.Parse(current_text);
  227. decimal meterStart = 0;
  228. string energyRegister_text = item.sampledValue.Where(x => x.measurand == Measurand.Energy_Active_Import_Register).Select(x => x.value).FirstOrDefault();
  229. decimal energyRegister = decimal.Parse(energyRegister_text);
  230. using (var maindb = new MainDBContext())
  231. {
  232. meterStart = maindb.TransactionRecord.Where(x => x.Id == _request.transactionId.Value).Select(x => x.MeterStart).FirstOrDefault();
  233. }
  234. item.sampledValue.Add(new SampledValue()
  235. {
  236. context = ReadingContext.Sample_Periodic,
  237. format = ValueFormat.Raw,
  238. location = Location.Outlet,
  239. phase = Phase.L1_N,
  240. unit = UnitOfMeasure.kWh,
  241. measurand = Measurand.Energy_Active_Import_Interval,
  242. value = decimal.Divide(decimal.Subtract(energyRegister, meterStart), (decimal)1000).ToString()
  243. });
  244. item.sampledValue.Add(new SampledValue()
  245. {
  246. context = ReadingContext.Sample_Periodic,
  247. format = ValueFormat.Raw,
  248. location = Location.Outlet,
  249. phase = Phase.L1_N,
  250. unit = UnitOfMeasure.kW,
  251. measurand = Measurand.Power_Active_Import,
  252. value = decimal.Divide(decimal.Multiply(voltage, current), (decimal)1000).ToString()
  253. });
  254. }
  255. foreach (var sampleVaule in item.sampledValue)
  256. {
  257. decimal value = Convert.ToDecimal(sampleVaule.value);
  258. if (sampleVaule.context == ReadingContext.Sample_Periodic && sampleVaule.measurand == Measurand.Energy_Active_Import_Interval)
  259. {
  260. energy_kwh = sampleVaule.unit == UnitOfMeasure.Wh ? Decimal.Divide(value, 1000) : value;
  261. }
  262. string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
  263. "@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
  264. List<SqlParameter> parameter = new List<SqlParameter>
  265. {
  266. new SqlParameter("ChargeBoxId",session.ChargeBoxId),
  267. new SqlParameter("ConnectorId", (byte)_request.connectorId),
  268. new SqlParameter("Value",value),
  269. new SqlParameter("CreatedOn",item.timestamp),
  270. new SqlParameter("ContextId",sampleVaule.context.HasValue ? (int)sampleVaule.context : 0),
  271. new SqlParameter("FormatId",sampleVaule.format.HasValue ? (int)sampleVaule.format : 0),
  272. new SqlParameter("MeasurandId",sampleVaule.measurand.HasValue ? (int)sampleVaule.measurand : 0),
  273. new SqlParameter("PhaseId",sampleVaule.phase.HasValue ? (int)sampleVaule.phase : 0),
  274. new SqlParameter("LocationId",sampleVaule.location.HasValue ? (int)sampleVaule.location : 0),
  275. new SqlParameter("UnitId",sampleVaule.unit.HasValue ? (int)sampleVaule.unit : 0),
  276. new SqlParameter("TransactionId",_request.transactionId.HasValue?_request.transactionId:-1),
  277. };
  278. db.Database.ExecuteSqlCommand(sp, parameter.ToArray());
  279. }
  280. }
  281. }
  282. }
  283. // if (energy_kwh > 0)
  284. {
  285. try
  286. {
  287. if (session.IsBilling)
  288. if (session.IsBilling)
  289. {
  290. using (var db = new MainDBContext())
  291. {
  292. db.ServerMessage.Add(new ServerMessage()
  293. {
  294. ChargeBoxId = session.ChargeBoxId,
  295. CreatedBy = "Server",
  296. CreatedOn = DateTime.UtcNow,
  297. OutAction = Actions.DataTransfer.ToString(),
  298. OutRequest = JsonConvert.SerializeObject(
  299. new DataTransferRequest()
  300. {
  301. messageId = "ID_TxEnergy",
  302. vendorId = "Phihong Technology",
  303. data = JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = _request.connectorId })
  304. },
  305. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  306. SerialNo = Guid.NewGuid().ToString(),
  307. InMessage = string.Empty
  308. });
  309. db.SaveChanges();
  310. }
  311. }
  312. }
  313. catch (Exception ex)
  314. {
  315. Console.WriteLine(string.Format("{0} :{1}", session.ChargeBoxId + " RunningCost", ex.Message));
  316. }
  317. }
  318. var confirm = new MeterValuesConfirmation() { };
  319. result.Message = confirm;
  320. result.Success = true;
  321. }
  322. break;
  323. case Actions.StartTransaction:
  324. {
  325. StartTransactionRequest _request = request as StartTransactionRequest;
  326. int _transactionId = -1;
  327. var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
  328. var _idTagInfo = _request.idTag == "Backend" ? new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted } : await businessService.Authorize(session.ChargeBoxId, _request.idTag);
  329. //特例****飛宏客戶旗下的電樁,若遇到Portal沒回應的狀況 ~允許充電
  330. if (session.CustomerId.ToString().ToUpper() == "8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7" && _idTagInfo.status == AuthorizationStatus.ConcurrentTx)
  331. {
  332. _idTagInfo = new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted };
  333. }
  334. string accountBalance = "0";
  335. if (session.CustomerId.ToString().ToUpper() == "10C7F5BD-C89A-4E2A-8611-B617E0B41A73")
  336. {
  337. using (SqlConnection conn = new SqlConnection(webConnectionString))
  338. {
  339. var parameters = new DynamicParameters();
  340. parameters.Add("@IdTag", _request.idTag, DbType.String, ParameterDirection.Input);
  341. string strSql = "select parentIdTag from [dbo].[LocalListDetail] where ListId = 27 and IdTag=@IdTag; ";
  342. accountBalance = conn.ExecuteScalar<string>(strSql, parameters);
  343. }
  344. }
  345. using (var db = new MainDBContext())
  346. {
  347. var _CustomerId = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).Include(x => x.Customer).
  348. Select(x => x.CustomerId).FirstOrDefault();
  349. var _existedTx = db.TransactionRecord.Where(x => x.CustomerId == _CustomerId && x.ChargeBoxId == session.ChargeBoxId
  350. && x.ConnectorId == _request.connectorId && x.StartTime == _request.timestamp).Select(C => new { C.Id }).AsNoTracking().FirstOrDefault();
  351. TransactionRecord _newTransaction = new TransactionRecord();
  352. if (_existedTx == null)
  353. {
  354. _newTransaction = new TransactionRecord()
  355. {
  356. ChargeBoxId = session.ChargeBoxId,
  357. ConnectorId = (byte)_request.connectorId,
  358. CreatedOn = DateTime.UtcNow,
  359. StartIdTag = _request.idTag,
  360. MeterStart = _request.meterStart,
  361. CustomerId = _CustomerId,
  362. StartTime = _request.timestamp.ToUniversalTime(),
  363. ReservationId = _request.reservationId.HasValue ? _request.reservationId.Value : 0,
  364. Fee = !session.IsBilling ? string.Empty : JsonConvert.SerializeObject(session.ChargingPrices) + "|+" + accountBalance + "+" + "&" + session.ParkingFee + "&|" + session.Currency
  365. };
  366. db.TransactionRecord.Add(_newTransaction);
  367. db.SaveChanges();
  368. _transactionId = _newTransaction.Id;
  369. logger.Info("***************************************************** ");
  370. logger.Info(string.Format("{0} :TransactionId {1} ", session.ChargeBoxId, _newTransaction.Id));
  371. logger.Info("***************************************************** ");
  372. }
  373. else
  374. {
  375. _transactionId = _existedTx.Id;
  376. logger.Error("Duplication ***************************************************** " + _existedTx.Id);
  377. }
  378. }
  379. var confirm = new StartTransactionConfirmation()
  380. {
  381. idTagInfo = _idTagInfo,
  382. transactionId = _transactionId
  383. };
  384. result.Message = confirm;
  385. result.Success = true;
  386. }
  387. break;
  388. case Actions.StopTransaction:
  389. {
  390. StopTransactionRequest _request = request as StopTransactionRequest;
  391. int _ConnectorId = 0;
  392. var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
  393. //特例****飛宏客戶旗下的電樁,若遇到Portal沒回應的狀況 ~允許充電
  394. var _idTagInfo = string.IsNullOrEmpty(_request.idTag) ? null : (_request.idTag == "Backend" ? new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted } : await businessService.Authorize(session.ChargeBoxId, _request.idTag));
  395. if (session.CustomerId.ToString().ToUpper() == "8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7" && _idTagInfo != null && _idTagInfo.status == AuthorizationStatus.ConcurrentTx)
  396. {
  397. _idTagInfo = new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted };
  398. }
  399. using (var db = new MainDBContext())
  400. {
  401. var transaction = db.TransactionRecord.Where(x => x.Id == _request.transactionId
  402. && x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
  403. //遠傳太久以前的停止充電 直接拒絕 避免電樁持續重送~~~~~~~
  404. if (_request.timestamp < new DateTime(2021, 11, 1))
  405. {
  406. var confirm = new StopTransactionConfirmation()
  407. {
  408. idTagInfo = new IdTagInfo()
  409. {
  410. status = AuthorizationStatus.Invalid
  411. }
  412. };
  413. result.Message = confirm;
  414. result.Success = true;
  415. return result;
  416. }
  417. if (transaction != null)
  418. {
  419. _ConnectorId = transaction.ConnectorId;
  420. transaction.MeterStop = _request.meterStop;
  421. transaction.StopTime = _request.timestamp.ToUniversalTime();
  422. transaction.StopReasonId = _request.reason.HasValue ? (int)_request.reason.Value : 0;
  423. transaction.StopIdTag = _request.idTag;
  424. transaction.Receipt = string.Empty;
  425. transaction.Cost = session.IsBilling ? -1 : 0;
  426. await db.SaveChangesAsync();
  427. var confirm = new StopTransactionConfirmation()
  428. {
  429. idTagInfo = _idTagInfo
  430. };
  431. if (session.IsBilling)
  432. {
  433. db.ServerMessage.Add(new ServerMessage()
  434. {
  435. ChargeBoxId = session.ChargeBoxId,
  436. CreatedBy = "Server",
  437. CreatedOn = DateTime.UtcNow,
  438. OutAction = Actions.DataTransfer.ToString(),
  439. OutRequest = JsonConvert.SerializeObject(
  440. new DataTransferRequest()
  441. {
  442. messageId = "ID_TxEnergy",
  443. vendorId = "Phihong Technology",
  444. data = JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = transaction.ConnectorId })
  445. },
  446. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  447. SerialNo = Guid.NewGuid().ToString(),
  448. InMessage = string.Empty
  449. });
  450. db.SaveChanges();
  451. }
  452. result.Message = confirm;
  453. result.Success = true;
  454. }
  455. else
  456. {
  457. result.Exception = new Exception("Can't find transactionId " + _request.transactionId);
  458. }
  459. }
  460. if (_request.transactionData != null)
  461. {
  462. if (_request.transactionData.Count > 0)
  463. {
  464. using (var _meterDb = new MeterValueDBContext())
  465. {
  466. foreach (var item in _request.transactionData)
  467. {
  468. foreach (var sampleVaule in item.sampledValue)
  469. {
  470. decimal value = Convert.ToDecimal(sampleVaule.value);
  471. string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
  472. "@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
  473. List<SqlParameter> parameter = new List<SqlParameter>
  474. {
  475. new SqlParameter("ChargeBoxId",session.ChargeBoxId),
  476. new SqlParameter("ConnectorId", (byte)_ConnectorId),
  477. new SqlParameter("Value",value),
  478. new SqlParameter("CreatedOn",item.timestamp),
  479. new SqlParameter("ContextId",sampleVaule.context.HasValue ? (int)sampleVaule.context : 0),
  480. new SqlParameter("FormatId",sampleVaule.format.HasValue ? (int)sampleVaule.format : 0),
  481. new SqlParameter("MeasurandId",sampleVaule.measurand.HasValue ? (int)sampleVaule.measurand : 0),
  482. new SqlParameter("PhaseId",sampleVaule.phase.HasValue ? (int)sampleVaule.phase : 0),
  483. new SqlParameter("LocationId",sampleVaule.location.HasValue ? (int)sampleVaule.location : 0),
  484. new SqlParameter("UnitId",sampleVaule.unit.HasValue ? (int)sampleVaule.unit : 0),
  485. new SqlParameter("TransactionId",_request.transactionId),
  486. };
  487. _meterDb.Database.ExecuteSqlCommand(sp, parameter.ToArray());
  488. }
  489. }
  490. }
  491. }
  492. }
  493. }
  494. break;
  495. case Actions.Authorize:
  496. {
  497. AuthorizeRequest _request = request as AuthorizeRequest;
  498. //特例****飛宏客戶旗下的電樁,若遇到Portal沒回應的狀況 ~允許充電
  499. var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
  500. var confirm = new AuthorizeConfirmation()
  501. {
  502. idTagInfo = _request.idTag == "Backend" ? new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted } : await businessService.Authorize(session.ChargeBoxId, _request.idTag)
  503. };
  504. if (session.CustomerId.ToString().ToUpper() == "8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7" && confirm.idTagInfo.status == AuthorizationStatus.ConcurrentTx)
  505. {
  506. confirm.idTagInfo = new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted };
  507. }
  508. result.Message = confirm;
  509. result.Success = true;
  510. }
  511. break;
  512. default:
  513. {
  514. Console.WriteLine(string.Format("Not Implement {0} Logic(ExecuteCoreRequest)", request.GetType().ToString().Replace("OCPPPackage.Messages.Core.", "")));
  515. }
  516. break;
  517. }
  518. }
  519. catch (Exception ex)
  520. {
  521. logger.Fatal(string.Format("chargeBoxId:{0} {1}", session.ChargeBoxId, action));
  522. logger.Fatal(string.Format("Data {0}", request.ToString()));
  523. logger.Fatal(string.Format("Error {0}", ex.ToString()));
  524. result.Exception = ex;
  525. }
  526. if (action == Actions.Heartbeat)
  527. {
  528. watch.Stop();
  529. if (watch.ElapsedMilliseconds / 1000 > 3)
  530. {
  531. logger.Error("Processing Hearbeat costs " + watch.ElapsedMilliseconds / 1000 + " seconds");
  532. }
  533. }
  534. return result;
  535. }
  536. internal MessageResult ExecuteCoreConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
  537. {
  538. MessageResult result = new MessageResult() { Success = true };
  539. try
  540. {
  541. switch (action)
  542. {
  543. case Actions.DataTransfer:
  544. {
  545. DataTransferConfirmation _confirm = confirm as DataTransferConfirmation;
  546. DataTransferRequest _request = _confirm.GetRequest() as DataTransferRequest;
  547. using (var db = new MainDBContext())
  548. {
  549. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  550. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  551. if (operation != null)
  552. {
  553. operation.FinishedOn = DateTime.UtcNow;
  554. operation.Status = 1;//電樁有回覆
  555. operation.EVSE_Status = (int)_confirm.status;
  556. operation.EVSE_Value = string.IsNullOrEmpty(_confirm.data) ? "" : _confirm.data;
  557. db.SaveChanges();
  558. }
  559. if (_request.messageId == "ID_FirmwareVersion")
  560. {
  561. var machine = new Machine() { Id = session.MachineId };
  562. if (machine != null)
  563. {
  564. db.Configuration.AutoDetectChangesEnabled = false;
  565. db.Configuration.ValidateOnSaveEnabled = false;
  566. db.Machine.Attach(machine);
  567. machine.BoardVersions = _confirm.data;
  568. db.Entry(machine).Property(x => x.BoardVersions).IsModified = true;
  569. db.SaveChanges();
  570. }
  571. }
  572. if (_request.messageId == "ID_TxEnergy")
  573. {
  574. if (_confirm.status == DataTransferStatus.Accepted)
  575. {
  576. string receipt = string.Empty;
  577. List<ChargingBill> bill = new List<ChargingBill>();
  578. List<ChargingPrice> chargingPrices = new List<ChargingPrice>();
  579. var txEnergy = JsonConvert.DeserializeObject<TransactionEnergy>(_confirm.data);
  580. var feedto = db.TransactionRecord.Where(x => x.Id == txEnergy.TxId).Select(x => new { Id = x.Id, ConnectorId = x.ConnectorId, Fee = x.Fee, StopTime = x.StopTime, StartTime = x.StartTime }).FirstOrDefault();
  581. if (feedto == null || string.IsNullOrEmpty(feedto.Fee)) return result;
  582. string currency = feedto.Fee.Substring(feedto.Fee.Length - 3);
  583. decimal sum = 0;
  584. if (feedto.Fee.Length > 10)
  585. {
  586. chargingPrices = JsonConvert.DeserializeObject<List<ChargingPrice>>(feedto.Fee.Split('|')[0]);
  587. foreach (var item in txEnergy.PeriodEnergy)
  588. {
  589. DateTime dt = new DateTime(2021, 01, 01, int.Parse(item.Key), 0, 0, DateTimeKind.Utc);
  590. string startTime = dt.ToString("hh:mm tt", new CultureInfo("en-us"));
  591. decimal perfee = 0;
  592. //小數點無條件捨去到第4位
  593. var periodEnergy = (decimal)((int)Decimal.Multiply(item.Value, 10000) / (double)10000);
  594. if (chargingPrices.Count == 1)
  595. {
  596. perfee = Decimal.Multiply(periodEnergy, chargingPrices[0].Fee);
  597. if (bill.Count == 0)
  598. {
  599. bill.Add(new ChargingBill()
  600. {
  601. StartTime = "12:00 AM",
  602. EndTime = "11:59 PM",
  603. Fee = chargingPrices[0].Fee
  604. });
  605. }
  606. bill[0].PeriodEnergy += periodEnergy;
  607. }
  608. else
  609. {
  610. var price = chargingPrices.Where(x => x.StartTime == startTime).FirstOrDefault();
  611. perfee = Decimal.Multiply(periodEnergy, price.Fee);
  612. bill.Add(new ChargingBill()
  613. {
  614. StartTime = price.StartTime,
  615. EndTime = price.EndTime,
  616. PeriodEnergy = periodEnergy,
  617. Fee = price.Fee,
  618. });
  619. }
  620. if (bill.Count > 0)
  621. {
  622. bill[bill.Count - 1].Total += DollarRounding(perfee, session.Currency);
  623. sum += bill[bill.Count - 1].Total;
  624. if (bill.Count == 1)
  625. {
  626. bill[bill.Count - 1].Total = DollarRounding(Decimal.Multiply(bill[0].PeriodEnergy, bill[0].Fee), session.Currency);
  627. sum = bill[bill.Count - 1].Total;
  628. }
  629. }
  630. }
  631. }
  632. if (feedto.StopTime != GlobalConfig.DefaultNullTime)
  633. {
  634. // 計算停車費
  635. var fee = decimal.Parse(feedto.Fee.Split('&')[1]);
  636. decimal accountBalance = 0;
  637. var stoptime = DateTime.Parse(feedto.StopTime.ToString("yyyy/MM/dd HH:mm"));
  638. var starttime = DateTime.Parse(feedto.StartTime.ToString("yyyy/MM/dd HH:mm"));
  639. decimal.TryParse(feedto.Fee.Split('+')[1], out accountBalance);
  640. var totalHours = stoptime.Subtract(starttime).TotalHours;
  641. var parkingCost = Decimal.Multiply((decimal)totalHours, fee);
  642. parkingCost = DollarRounding(parkingCost, session.Currency);
  643. var tx = db.TransactionRecord.Where(x => x.Id == txEnergy.TxId).FirstOrDefault();
  644. if (tx == null)
  645. {
  646. Console.WriteLine("Tx is empty");
  647. return result;
  648. }
  649. if (tx.UploadedtoTTIA) return result;
  650. var startTime = new DateTime(tx.StartTime.Year, tx.StartTime.Month, tx.StartTime.Day, tx.StartTime.Hour, 0, 0);
  651. List<ChargingBill> confirmbill = new List<ChargingBill>();
  652. receipt = string.Format("({0} )Energy:", bill.Sum(x => x.PeriodEnergy));
  653. while (startTime < tx.StopTime)
  654. {
  655. if (bill.Count == 1)
  656. {
  657. confirmbill = bill;
  658. receipt += string.Format("| {0} - {1}:| {2} kWh @ ${3}/kWh=${4}", tx.StartTime.ToString("hh:mm tt", new CultureInfo("en-us")), confirmbill[0].PeriodEnergy.ToString("0.0000"), tx.StopTime.ToString("hh:mm tt", new CultureInfo("en-us")), bill[0].Fee, bill[0].Total);
  659. break;
  660. }
  661. if (bill.Count > 1)
  662. {
  663. var time = startTime.ToString("hh:mm tt", new CultureInfo("en-us"));
  664. var tt = bill.Where(x => x.StartTime == time).FirstOrDefault();
  665. confirmbill.Add(tt);
  666. if (confirmbill.Count == 1)
  667. {
  668. confirmbill[0].StartTime = tx.StartTime.ToString("hh:mm tt", new CultureInfo("en-us"));
  669. }
  670. var stopTimeText = tx.StopTime.ToString("hh:mm tt", new CultureInfo("en-us"));
  671. if (confirmbill[confirmbill.Count - 1].StartTime.Contains(stopTimeText.Split(' ')[1]))
  672. {
  673. var subHourText = (int.Parse(stopTimeText.Split(':')[0])).ToString();
  674. subHourText = subHourText.Length == 1 ? "0" + subHourText : subHourText;
  675. if (confirmbill[confirmbill.Count - 1].StartTime.Contains(subHourText))
  676. {
  677. confirmbill[confirmbill.Count - 1].EndTime = stopTimeText;
  678. }
  679. }
  680. receipt += string.Format("| {0} - {1}:| {2} kWh @ ${3}/kWh=${4}", confirmbill[confirmbill.Count - 1].StartTime, confirmbill[confirmbill.Count - 1].EndTime,
  681. confirmbill[confirmbill.Count - 1].PeriodEnergy.ToString("0.0000"), confirmbill[confirmbill.Count - 1].Fee, confirmbill[confirmbill.Count - 1].Total);
  682. if (confirmbill.Count == 24) break;
  683. }
  684. startTime = startTime.AddHours(1);
  685. }
  686. if (confirmbill.Count > 1)
  687. {
  688. receipt += string.Format("|Total Energy Fee : ${0}", confirmbill.Sum(x => x.Total));
  689. }
  690. receipt += string.Format("|Parking Fee: | {0} - {1} @ ${2}/hr=${3}", feedto.StartTime.ToString("hh:mm tt", new CultureInfo("en-us")),
  691. feedto.StopTime.ToString("hh:mm tt", new CultureInfo("en-us")), fee, parkingCost);
  692. tx.Cost = sum + parkingCost;
  693. tx.Receipt = receipt;
  694. tx.UploadedtoTTIA = true;
  695. db.Configuration.AutoDetectChangesEnabled = false;
  696. db.Configuration.ValidateOnSaveEnabled = false;
  697. db.TransactionRecord.Attach(tx);
  698. db.Entry(tx).Property(x => x.Cost).IsModified = true;
  699. db.Entry(tx).Property(x => x.Receipt).IsModified = true;
  700. db.Entry(tx).Property(x => x.UploadedtoTTIA).IsModified = true;
  701. db.ServerMessage.Add(new ServerMessage()
  702. {
  703. ChargeBoxId = session.ChargeBoxId,
  704. CreatedBy = "Server",
  705. CreatedOn = DateTime.UtcNow,
  706. OutAction = Actions.DataTransfer.ToString(),
  707. OutRequest = JsonConvert.SerializeObject(
  708. new DataTransferRequest()
  709. {
  710. messageId = "FinalCost",
  711. vendorId = "Phihong Technology",
  712. data = JsonConvert.SerializeObject(new
  713. {
  714. txId = txEnergy.TxId,
  715. // description = string.Format("Connection Fee: $0.00 {0}; Session Fee: ${1} {0}; Occupancy Fee: " +
  716. //"${2} {0}; Total Cost: ${3} {0}; Account Balance: ${4} {0}", currency, sum, parkingCost, tx.Cost, accountBalance - tx.Cost)
  717. description = JsonConvert.SerializeObject(new
  718. {
  719. chargedEnergy = bill.Sum(x => x.PeriodEnergy),
  720. chargingFee = sum,
  721. parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
  722. parkingFee = parkingCost,
  723. currency = currency,
  724. couponPoint = 0,
  725. accountBalance = accountBalance - tx.Cost
  726. })
  727. })
  728. },
  729. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  730. SerialNo = Guid.NewGuid().ToString(),
  731. InMessage = string.Empty
  732. }); ;
  733. db.SaveChanges();
  734. using (var meterdb = new MeterValueDBContext())
  735. {
  736. string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
  737. "@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
  738. List<SqlParameter> parameter = new List<SqlParameter>
  739. {
  740. new SqlParameter("ChargeBoxId",session.ChargeBoxId),
  741. new SqlParameter("ConnectorId", (byte)feedto.ConnectorId),
  742. new SqlParameter("Value",sum),
  743. new SqlParameter("CreatedOn",DateTime.UtcNow),
  744. new SqlParameter("ContextId",(int)ReadingContext.Sample_Periodic),
  745. new SqlParameter("FormatId",(int)ValueFormat.Raw),
  746. new SqlParameter("MeasurandId",(int)Measurand.TotalCost),
  747. new SqlParameter("PhaseId", -1),
  748. new SqlParameter("LocationId", -1),
  749. new SqlParameter("UnitId", -1),
  750. new SqlParameter("TransactionId",feedto.Id),
  751. };
  752. meterdb.Database.ExecuteSqlCommand(sp, parameter.ToArray());
  753. }
  754. using (SqlConnection conn = new SqlConnection(webConnectionString))
  755. {
  756. var parameters = new DynamicParameters();
  757. parameters.Add("@IdTag", tx.StartIdTag, DbType.String, ParameterDirection.Input);
  758. parameters.Add("@parentIdTag", accountBalance - tx.Cost, DbType.String, ParameterDirection.Input);
  759. string strSql = "update [dbo].[LocalListDetail] set parentIdTag =@parentIdTag where ListId = 27 and IdTag=@IdTag; ";
  760. conn.Execute(strSql, parameters);
  761. }
  762. if (tx.CustomerId == Guid.Parse("10C7F5BD-C89A-4E2A-8611-B617E0B41A73"))
  763. {
  764. var mail_response = new OuterHttpClient().PostFormDataAsync("http://ocpp.phihong.com.tw/CDFA/" + tx.Id, new Dictionary<string, string>()
  765. {
  766. { "email","2"},
  767. { "to","wonderj@phihongusa.com;jessica_tseng@phihong.com.tw"}
  768. //{ "to","jessica_tseng@phihong.com.tw"}
  769. }, null);
  770. Console.WriteLine(JsonConvert.SerializeObject(mail_response));
  771. }
  772. }
  773. else
  774. {
  775. // 計算停車費
  776. var fee = decimal.Parse(feedto.Fee.Split('&')[1]);
  777. decimal accountBalance = 0;
  778. var stoptime = DateTime.Parse(DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm"));
  779. var starttime = DateTime.Parse(feedto.StartTime.ToString("yyyy/MM/dd HH:mm"));
  780. decimal.TryParse(feedto.Fee.Split('+')[1], out accountBalance);
  781. var totalHours = stoptime.Subtract(starttime).TotalHours;
  782. var parkingCost = Decimal.Multiply((decimal)totalHours, fee);
  783. parkingCost = DollarRounding(parkingCost, session.Currency);
  784. db.ServerMessage.Add(new ServerMessage()
  785. {
  786. ChargeBoxId = session.ChargeBoxId,
  787. CreatedBy = "Server",
  788. CreatedOn = DateTime.UtcNow,
  789. OutAction = Actions.DataTransfer.ToString(),
  790. OutRequest = JsonConvert.SerializeObject(
  791. new DataTransferRequest()
  792. {
  793. messageId = "RunningCost",
  794. vendorId = "Phihong Technology",
  795. data = JsonConvert.SerializeObject(new
  796. {
  797. txId = txEnergy.TxId,
  798. //description = string.Format("Connection Fee: $0.00 {0}; Session Fee: ${1} {0}; Occupancy Fee: " +
  799. //"${2} {0}; Total Cost: ${3} {0}; Account Balance: $0.00 {0}", currency, sum, parkingCost, sum + parkingCost),
  800. description = JsonConvert.SerializeObject(new
  801. {
  802. chargedEnergy = bill.Sum(x => x.PeriodEnergy),
  803. chargingFee = sum,
  804. parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
  805. parkingFee = parkingCost,
  806. currency = currency
  807. })
  808. })
  809. },
  810. new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
  811. SerialNo = Guid.NewGuid().ToString(),
  812. InMessage = string.Empty
  813. }); ;
  814. db.SaveChanges();
  815. using (var meterdb = new MeterValueDBContext())
  816. {
  817. string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
  818. "@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
  819. List<SqlParameter> parameter = new List<SqlParameter>
  820. {
  821. new SqlParameter("ChargeBoxId",session.ChargeBoxId),
  822. new SqlParameter("ConnectorId", (byte)feedto.ConnectorId),
  823. new SqlParameter("Value",sum),
  824. new SqlParameter("CreatedOn",DateTime.UtcNow),
  825. new SqlParameter("ContextId",(int)ReadingContext.Sample_Periodic),
  826. new SqlParameter("FormatId",(int)ValueFormat.Raw),
  827. new SqlParameter("MeasurandId",(int)Measurand.ChargingCost),
  828. new SqlParameter("PhaseId", -1),
  829. new SqlParameter("LocationId", -1),
  830. new SqlParameter("UnitId", -1),
  831. new SqlParameter("TransactionId",feedto.Id),
  832. };
  833. meterdb.Database.ExecuteSqlCommand(sp, parameter.ToArray());
  834. }
  835. }
  836. }
  837. }
  838. if(_request.messageId== "ID_GetTxUserInfo")
  839. {
  840. var txUserInfo = JsonConvert.DeserializeObject<ID_GetTxUserInfo>(_confirm.data);
  841. if (session.CustomerId == new Guid("009E603C-79CD-4620-A2B8-D9349C0E8AD8"))
  842. {
  843. var request = new
  844. {
  845. ChargeBoxId = session.ChargeBoxId,
  846. ConnectorId = txUserInfo.ConnectorId,
  847. SessionId = txUserInfo.TxId,
  848. SerialNo = txUserInfo.SerialNo,
  849. StartTime = txUserInfo.StartTime.ToString(GlobalConfig.UTC_DATETIMEFORMAT)
  850. };
  851. var response = httpClient.Post(GlobalConfig.TCC_API_URL + "start_session", new Dictionary<string, string>()
  852. {
  853. { "PartnerId",session.CustomerId.ToString()}
  854. }, request, GlobalConfig.TCC_SALTKEY);
  855. logger.Debug(JsonConvert.SerializeObject(response));
  856. }
  857. }
  858. }
  859. }
  860. break;
  861. case Actions.ChangeAvailability:
  862. {
  863. ChangeAvailabilityConfirmation _confirm = confirm as ChangeAvailabilityConfirmation;
  864. ChangeAvailabilityRequest _request = _confirm.GetRequest() as ChangeAvailabilityRequest;
  865. using (var db = new MainDBContext())
  866. {
  867. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  868. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  869. if (operation != null)
  870. {
  871. operation.FinishedOn = DateTime.UtcNow;
  872. operation.Status = 1;//電樁有回覆
  873. operation.EVSE_Status = (int)_confirm.status;
  874. operation.EVSE_Value = _confirm.status.ToString();
  875. db.SaveChanges();
  876. }
  877. }
  878. }
  879. break;
  880. case Actions.ClearCache:
  881. {
  882. ClearCacheConfirmation _confirm = confirm as ClearCacheConfirmation;
  883. ClearCacheRequest _request = _confirm.GetRequest() as ClearCacheRequest;
  884. using (var db = new MainDBContext())
  885. {
  886. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  887. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  888. if (operation != null)
  889. {
  890. operation.FinishedOn = DateTime.UtcNow;
  891. operation.Status = 1;//電樁有回覆
  892. operation.EVSE_Status = (int)_confirm.status;
  893. operation.EVSE_Value = _confirm.status.ToString();
  894. db.SaveChanges();
  895. }
  896. }
  897. }
  898. break;
  899. case Actions.RemoteStartTransaction:
  900. {
  901. RemoteStartTransactionConfirmation _confirm = confirm as RemoteStartTransactionConfirmation;
  902. RemoteStartTransactionRequest _request = _confirm.GetRequest() as RemoteStartTransactionRequest;
  903. using (var db = new MainDBContext())
  904. {
  905. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  906. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  907. if (operation != null)
  908. {
  909. operation.FinishedOn = DateTime.UtcNow;
  910. operation.Status = 1;//電樁有回覆
  911. operation.EVSE_Status = (int)_confirm.status;
  912. operation.EVSE_Value = _confirm.status.ToString();
  913. db.SaveChanges();
  914. }
  915. }
  916. }
  917. break;
  918. case Actions.RemoteStopTransaction:
  919. {
  920. RemoteStopTransactionConfirmation _confirm = confirm as RemoteStopTransactionConfirmation;
  921. RemoteStopTransactionRequest _request = _confirm.GetRequest() as RemoteStopTransactionRequest;
  922. using (var db = new MainDBContext())
  923. {
  924. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  925. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  926. if (operation != null)
  927. {
  928. operation.FinishedOn = DateTime.UtcNow;
  929. operation.Status = 1;//電樁有回覆
  930. operation.EVSE_Status = (int)_confirm.status;
  931. operation.EVSE_Value = _confirm.status.ToString();
  932. db.SaveChanges();
  933. }
  934. }
  935. }
  936. break;
  937. case Actions.Reset:
  938. {
  939. ResetConfirmation _confirm = confirm as ResetConfirmation;
  940. ResetRequest _request = _confirm.GetRequest() as ResetRequest;
  941. using (var db = new MainDBContext())
  942. {
  943. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  944. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  945. if (operation != null)
  946. {
  947. operation.FinishedOn = DateTime.UtcNow;
  948. operation.Status = 1;//電樁有回覆
  949. operation.EVSE_Status = (int)_confirm.status;
  950. operation.EVSE_Value = _confirm.status.ToString();
  951. db.SaveChanges();
  952. }
  953. }
  954. }
  955. break;
  956. case Actions.ChangeConfiguration:
  957. {
  958. ChangeConfigurationConfirmation _confirm = confirm as ChangeConfigurationConfirmation;
  959. ChangeConfigurationRequest _request = _confirm.GetRequest() as ChangeConfigurationRequest;
  960. using (var db = new MainDBContext())
  961. {
  962. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  963. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  964. if (operation != null)
  965. {
  966. operation.FinishedOn = DateTime.UtcNow;
  967. operation.Status = 1;//電樁有回覆
  968. operation.EVSE_Status = (int)_confirm.status;
  969. operation.EVSE_Value = _confirm.status.ToString();
  970. }
  971. if (_confirm.status == Packet.Messages.SubTypes.ConfigurationStatus.Accepted || _confirm.status == Packet.Messages.SubTypes.ConfigurationStatus.RebootRequired)
  972. {
  973. var configure = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId).ToList();
  974. var foundConfig = configure.Find(x => x.ConfigureName == _request.key);
  975. if (foundConfig != null)
  976. {
  977. foundConfig.ReadOnly = false;
  978. foundConfig.ConfigureSetting = _request.value;
  979. }
  980. else
  981. {
  982. db.MachineConfiguration.Add(new MachineConfiguration()
  983. {
  984. ChargeBoxId = session.ChargeBoxId,
  985. ConfigureName = _request.key,
  986. ReadOnly = false,
  987. ConfigureSetting = _request.value
  988. });
  989. }
  990. }
  991. db.SaveChanges();
  992. }
  993. }
  994. break;
  995. case Actions.GetConfiguration:
  996. {
  997. try
  998. {
  999. GetConfigurationConfirmation _confirm = confirm as GetConfigurationConfirmation;
  1000. // GetConfigurationRequest _request = _confirm.GetRequest() as GetConfigurationRequest;
  1001. using (var db = new MainDBContext())
  1002. {
  1003. var configure = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId).ToList();
  1004. if (_confirm.configurationKey != null)
  1005. {
  1006. foreach (var item in _confirm.configurationKey)
  1007. {
  1008. string oldValue = string.Empty;
  1009. if (item.key == null)
  1010. {
  1011. Console.WriteLine("*********************");
  1012. }
  1013. var foundConfig = configure.Find(x => x.ConfigureName == item.key);
  1014. if (foundConfig != null)
  1015. {
  1016. if (foundConfig.ConfigureName == null)
  1017. {
  1018. Console.WriteLine("*********************");
  1019. }
  1020. if (foundConfig.ConfigureName == "SecurityProfile")
  1021. {
  1022. oldValue = foundConfig.ConfigureSetting;
  1023. }
  1024. foundConfig.ReadOnly = item.IsReadOnly;
  1025. foundConfig.ConfigureSetting = string.IsNullOrEmpty(item.value) ? string.Empty : item.value;
  1026. }
  1027. else
  1028. {
  1029. db.MachineConfiguration.Add(new MachineConfiguration()
  1030. {
  1031. ChargeBoxId = session.ChargeBoxId,
  1032. ConfigureName = item.key,
  1033. ReadOnly = item.IsReadOnly,
  1034. ConfigureSetting = string.IsNullOrEmpty(item.value) ? string.Empty : item.value,
  1035. Exists = true
  1036. });
  1037. }
  1038. }
  1039. }
  1040. if (_confirm.unknownKey != null)
  1041. {
  1042. foreach (var item in _confirm.unknownKey)
  1043. {
  1044. var foundConfig = configure.Find(x => x.ConfigureName == item);
  1045. if (foundConfig != null)
  1046. {
  1047. foundConfig.ReadOnly = true;
  1048. foundConfig.ConfigureSetting = string.Empty;
  1049. foundConfig.Exists = false;
  1050. }
  1051. else
  1052. {
  1053. db.MachineConfiguration.Add(new MachineConfiguration()
  1054. {
  1055. ChargeBoxId = session.ChargeBoxId,
  1056. ConfigureName = item
  1057. });
  1058. }
  1059. }
  1060. }
  1061. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  1062. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  1063. if (operation != null)
  1064. {
  1065. operation.FinishedOn = DateTime.UtcNow;
  1066. operation.Status = 1;//電樁有回覆
  1067. operation.EVSE_Status = 1;
  1068. operation.EVSE_Value = JsonConvert.SerializeObject(_confirm.configurationKey, Formatting.None);
  1069. }
  1070. db.SaveChanges();
  1071. }
  1072. }
  1073. catch (Exception ex)
  1074. {
  1075. logger.Error(ex.ToString());
  1076. }
  1077. }
  1078. break;
  1079. case Actions.UnlockConnector:
  1080. {
  1081. UnlockConnectorConfirmation _confirm = confirm as UnlockConnectorConfirmation;
  1082. UnlockConnectorRequest _request = _confirm.GetRequest() as UnlockConnectorRequest;
  1083. using (var db = new MainDBContext())
  1084. {
  1085. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  1086. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  1087. if (operation != null)
  1088. {
  1089. operation.FinishedOn = DateTime.UtcNow;
  1090. operation.Status = 1;//電樁有回覆
  1091. operation.EVSE_Status = (int)_confirm.status;
  1092. operation.EVSE_Value = _confirm.status.ToString();
  1093. db.SaveChanges();
  1094. }
  1095. }
  1096. }
  1097. break;
  1098. default:
  1099. {
  1100. Console.WriteLine(string.Format("Not Implement {0} Logic(ExecuteCoreConfirm)", confirm.GetType().ToString().Replace("OCPPPackage.Messages.Core.", "")));
  1101. }
  1102. break;
  1103. }
  1104. }
  1105. catch (Exception ex)
  1106. {
  1107. logger.Debug("123 " + action + " " + ex.ToString());
  1108. }
  1109. return result;
  1110. }
  1111. internal MessageResult ReceivedCoreError(Actions action, string errorMsg, ClientData session, string requestId)
  1112. {
  1113. MessageResult result = new MessageResult() { Success = true };
  1114. switch (action)
  1115. {
  1116. case Actions.ChangeAvailability:
  1117. case Actions.ChangeConfiguration:
  1118. case Actions.ClearCache:
  1119. case Actions.RemoteStartTransaction:
  1120. case Actions.RemoteStopTransaction:
  1121. case Actions.Reset:
  1122. case Actions.GetConfiguration:
  1123. case Actions.UnlockConnector:
  1124. case Actions.DataTransfer:
  1125. {
  1126. if (action == Actions.DataTransfer)
  1127. {
  1128. logger.Debug(string.Format("DataTransfer Error {0}: {1}", session.ChargeBoxId, requestId));
  1129. }
  1130. using (var db = new MainDBContext())
  1131. {
  1132. var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
  1133. x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
  1134. if (operation != null)
  1135. {
  1136. operation.FinishedOn = DateTime.UtcNow;
  1137. operation.Status = 1;//電樁有回覆
  1138. operation.EVSE_Status = (int)255;//錯誤
  1139. operation.EVSE_Value = errorMsg;
  1140. db.SaveChanges();
  1141. }
  1142. }
  1143. }
  1144. break;
  1145. default:
  1146. {
  1147. Console.WriteLine(string.Format("Not Implement {0} Logic(ReceivedCoreError)", action));
  1148. }
  1149. break;
  1150. }
  1151. return result;
  1152. }
  1153. /// <summary>
  1154. /// 依據幣值處理4捨5入
  1155. /// </summary>
  1156. /// <param name="money"></param>
  1157. /// <param name="currency"></param>
  1158. /// <returns></returns>
  1159. private decimal DollarRounding(decimal money, string currency)
  1160. {
  1161. if (currency == "USD" || currency == "EUR")
  1162. {
  1163. //0.4867
  1164. if ((double)((int)(money * 100) + 0.5) <= (double)(money * 100))
  1165. {
  1166. //money = Decimal.Add(money, (decimal)0.01);//0.4967
  1167. }
  1168. money = Math.Round(money, 2, MidpointRounding.AwayFromZero);
  1169. money = Decimal.Parse(money.ToString("0.00"));
  1170. }
  1171. else
  1172. {
  1173. if ((double)((int)(money) + 0.5) <= (double)money)
  1174. {
  1175. // money = (int) money + 1;
  1176. }
  1177. money = Math.Round(money, 0, MidpointRounding.AwayFromZero);
  1178. money = Decimal.Parse(money.ToString("0"));
  1179. }
  1180. return money;
  1181. }
  1182. }
  1183. }