CoreProfileHandler.cs 99 KB

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