public static void Main(string[] args) { IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false) .Build(); try { // Force the EF model creation for faster startup using (OCPPCoreContext dbContext = new OCPPCoreContext(config)) { IModel model = dbContext.Model; } CreateHostBuilder(args).Build().Run(); } catch //(Exception e) { //logger.Error(e, "OCPP server stopped because of exception"); throw; } }
/// <summary> /// Helper function for writing a log entry in database /// </summary> private bool WriteMessageLog(string chargePointId, int?connectorId, string message, string result, string errorCode) { try { int dbMessageLog = Configuration.GetValue <int>("DbMessageLog", 0); if (dbMessageLog > 0 && !string.IsNullOrWhiteSpace(chargePointId)) { bool doLog = (dbMessageLog > 1 || (message != "BootNotification" && message != "Heartbeat" && message != "DataTransfer" && message != "StatusNotification")); if (doLog) { using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { MessageLog msgLog = new MessageLog(); msgLog.ChargePointId = chargePointId; msgLog.ConnectorId = connectorId; msgLog.LogTime = DateTime.UtcNow; msgLog.Message = message; msgLog.Result = result; msgLog.ErrorCode = errorCode; dbContext.MessageLogs.Add(msgLog); Logger.LogTrace("MessageLog => Writing entry '{0}'", message); dbContext.SaveChanges(); } return(true); } } } catch (Exception exp) { Logger.LogError(exp, "MessageLog => Error writing entry '{0}'", message); } return(false); }
public async Task <IActionResult> Index() { Logger.LogTrace("Index: Loading charge points with latest transactions..."); OverviewViewModel overviewModel = new OverviewViewModel(); overviewModel.ChargePoints = new List <ChargePointsOverviewViewModel>(); try { using (OCPPCoreContext dbContext = new OCPPCoreContext(this.Config)) { var chargeData = from cp in dbContext.ChargePoints from t in cp.Transactions .OrderByDescending(t => t.TransactionId) .DefaultIfEmpty() .Take(1) select new { cp, t }; ChargePointStatus[] statusList = null; string serverApiUrl = base.Config.GetValue <string>("ServerApiUrl"); string apiKeyConfig = base.Config.GetValue <string>("ApiKey"); if (!string.IsNullOrEmpty(serverApiUrl)) { bool serverError = false; try { using (var httpClient = new HttpClient()) { if (!serverApiUrl.EndsWith('/')) { serverApiUrl += "/"; } Uri uri = new Uri(serverApiUrl); uri = new Uri(uri, "Status"); httpClient.Timeout = new TimeSpan(0, 0, 4); // use short timeout // API-Key authentication? if (!string.IsNullOrWhiteSpace(apiKeyConfig)) { httpClient.DefaultRequestHeaders.Add("X-API-Key", apiKeyConfig); } else { Logger.LogWarning("Index: No API-Key configured!"); } HttpResponseMessage response = await httpClient.GetAsync(uri); if (response.StatusCode == System.Net.HttpStatusCode.OK) { string jsonData = await response.Content.ReadAsStringAsync(); if (!string.IsNullOrEmpty(jsonData)) { statusList = JsonConvert.DeserializeObject <ChargePointStatus[]>(jsonData); overviewModel.ServerConnection = true; } else { Logger.LogError("Index: Result of status web request is empty"); serverError = true; } } else { Logger.LogError("Index: Result of status web request => httpStatus={0}", response.StatusCode); serverError = true; } } Logger.LogInformation("Index: Result of status web request => Length={0}", statusList?.Length); } catch (Exception exp) { Logger.LogError(exp, "Index: Error in status web request => {0}", exp.Message); serverError = true; } if (serverError) { ViewBag.ErrorMsg = _localizer["ErrorOCPPServer"]; } } int i = 0; foreach (var cp in chargeData) { // count number of charge points i++; // Copy data in view model ChargePointsOverviewViewModel cpovm = new ChargePointsOverviewViewModel(); cpovm.ChargePointId = cp.cp.ChargePointId; cpovm.Name = cp.cp.Name; cpovm.Comment = cp.cp.Comment; if (cp.t != null) { cpovm.MeterStart = cp.t.MeterStart; cpovm.MeterStop = cp.t.MeterStop; cpovm.StartTime = cp.t.StartTime; cpovm.StopTime = cp.t.StopTime; // default status: active transaction or not? cpovm.ConnectorStatus = (cpovm.StopTime.HasValue) ? ConnectorStatus.Available : ConnectorStatus.Occupied; } else { cpovm.MeterStart = -1; cpovm.MeterStop = -1; cpovm.StartTime = null; cpovm.StopTime = null; // default status: Available cpovm.ConnectorStatus = ConnectorStatus.Available; } overviewModel.ChargePoints.Add(cpovm); if (statusList != null) { foreach (ChargePointStatus cpStatus in statusList) { if (cpStatus.Id.Equals(cpovm.ChargePointId, StringComparison.InvariantCultureIgnoreCase)) { // ChargePoint in statuslist => online cpovm.Online = true; if (cpStatus.EVSE1Status != ConnectorStatus.Undefined) { // TODO: display multiple connectors Logger.LogTrace("Index: Charge point '{0}' => Override status '{1}' to '{2}'", cpovm.ChargePointId, cpovm.ConnectorStatus, cpStatus.EVSE1Status); cpovm.ConnectorStatus = cpStatus.EVSE1Status; } if (cpovm.ConnectorStatus == ConnectorStatus.Occupied) { ChargingData chargingData = cpStatus.ChargingDataEVSE1; if (chargingData == null) { chargingData = cpStatus.ChargingDataEVSE2; } if (chargingData != null) { string currentCharge = string.Empty; if (chargingData.ChargeRateKW != null) { currentCharge = string.Format("{0:0.0}kW", chargingData.ChargeRateKW.Value); } if (chargingData.SoC != null) { if (!string.IsNullOrWhiteSpace(currentCharge)) { currentCharge += " | "; } currentCharge += string.Format("{0:0}%", chargingData.SoC.Value); } if (!string.IsNullOrWhiteSpace(currentCharge)) { cpovm.CurrentChargeData = currentCharge; } } } break; } } } } Logger.LogInformation("Index: Found {0} charge points", i); } } catch (Exception exp) { Logger.LogError(exp, "Index: Error loading charge points from database"); TempData["ErrMessage"] = exp.Message; return(RedirectToAction("Error", new { Id = "" })); } return(View(overviewModel)); }
public async Task Invoke(HttpContext context) { _logger.LogTrace("OCPPMiddleware => Websocket request: Path='{0}'", context.Request.Path); ChargePointStatus chargePointStatus = null; if (context.Request.Path.StartsWithSegments("/OCPP")) { string chargepointIdentifier; string[] parts = context.Request.Path.Value.Split('/'); if (string.IsNullOrWhiteSpace(parts[parts.Length - 1])) { // (Last part - 1) is chargepoint identifier chargepointIdentifier = parts[parts.Length - 2]; } else { // Last part is chargepoint identifier chargepointIdentifier = parts[parts.Length - 1]; } _logger.LogInformation("OCPPMiddleware => Connection request with chargepoint identifier = '{0}'", chargepointIdentifier); // Known chargepoint? if (!string.IsNullOrWhiteSpace(chargepointIdentifier)) { using (OCPPCoreContext dbContext = new OCPPCoreContext(_configuration)) { ChargePoint chargePoint = dbContext.Find <ChargePoint>(chargepointIdentifier); if (chargePoint != null) { _logger.LogInformation("OCPPMiddleware => SUCCESS: Found chargepoint with identifier={0}", chargePoint.ChargePointId); // Check optional chargepoint authentication if (!string.IsNullOrWhiteSpace(chargePoint.Username)) { // Chargepoint MUST send basic authentication header bool basicAuthSuccess = false; string authHeader = context.Request.Headers["Authorization"]; if (!string.IsNullOrEmpty(authHeader)) { string[] cred = System.Text.ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(authHeader.Substring(6))).Split(':'); if (cred.Length == 2 && chargePoint.Username == cred[0] && chargePoint.Password == cred[1]) { // Authentication match => OK _logger.LogInformation("OCPPMiddleware => SUCCESS: Basic authentication for chargepoint '{0}' match", chargePoint.ChargePointId); basicAuthSuccess = true; } else { // Authentication does NOT match => Failure _logger.LogWarning("OCPPMiddleware => FAILURE: Basic authentication for chargepoint '{0}' does NOT match", chargePoint.ChargePointId); } } if (basicAuthSuccess == false) { context.Response.Headers.Add("WWW-Authenticate", "Basic realm=\"OCPP.Core\""); context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; return; } } else if (!string.IsNullOrWhiteSpace(chargePoint.ClientCertThumb)) { // Chargepoint MUST send basic authentication header bool certAuthSuccess = false; X509Certificate2 clientCert = context.Connection.ClientCertificate; if (clientCert != null) { if (clientCert.Thumbprint.Equals(chargePoint.ClientCertThumb, StringComparison.InvariantCultureIgnoreCase)) { // Authentication match => OK _logger.LogInformation("OCPPMiddleware => SUCCESS: Certificate authentication for chargepoint '{0}' match", chargePoint.ChargePointId); certAuthSuccess = true; } else { // Authentication does NOT match => Failure _logger.LogWarning("OCPPMiddleware => FAILURE: Certificate authentication for chargepoint '{0}' does NOT match", chargePoint.ChargePointId); } } if (certAuthSuccess == false) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; return; } } else { _logger.LogInformation("OCPPMiddleware => No authentication for chargepoint '{0}' configured", chargePoint.ChargePointId); } // Store chargepoint data chargePointStatus = new ChargePointStatus(chargePoint); } else { _logger.LogWarning("OCPPMiddleware => FAILURE: Found no chargepoint with identifier={0}", chargepointIdentifier); } } } if (chargePointStatus != null) { if (context.WebSockets.IsWebSocketRequest) { // Match supported sub protocols string subProtocol = null; foreach (string supportedProtocol in SupportedProtocols) { if (context.WebSockets.WebSocketRequestedProtocols.Contains(supportedProtocol)) { subProtocol = supportedProtocol; break; } } if (string.IsNullOrEmpty(subProtocol)) { // Not matching protocol! => failure string protocols = string.Empty; foreach (string p in context.WebSockets.WebSocketRequestedProtocols) { if (string.IsNullOrEmpty(protocols)) { protocols += ","; } protocols += p; } _logger.LogWarning("OCPPMiddleware => No supported sub-protocol in '{0}' from charge station '{1}'", protocols, chargepointIdentifier); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; } else { chargePointStatus.Protocol = subProtocol; bool statusSuccess = false; try { _logger.LogTrace("OCPPMiddleware => Store/Update status object"); lock (_chargePointStatusDict) { // Check if this chargepoint already/still hat a status object if (_chargePointStatusDict.ContainsKey(chargepointIdentifier)) { // exists => check status if (_chargePointStatusDict[chargepointIdentifier].WebSocket.State != WebSocketState.Open) { // Closed or aborted => remove _chargePointStatusDict.Remove(chargepointIdentifier); } } _chargePointStatusDict.Add(chargepointIdentifier, chargePointStatus); statusSuccess = true; } } catch (Exception exp) { _logger.LogError(exp, "OCPPMiddleware => Error storing status object in dictionary => refuse connection"); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } if (statusSuccess) { // Handle socket communication _logger.LogTrace("OCPPMiddleware => Waiting for message..."); using (WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(subProtocol)) { _logger.LogTrace("OCPPMiddleware => WebSocket connection with charge point '{0}'", chargepointIdentifier); chargePointStatus.WebSocket = webSocket; if (subProtocol == Protocol_OCPP20) { // OCPP V2.0 await Receive20(chargePointStatus, context); } else { // OCPP V1.6 await Receive16(chargePointStatus, context); } } } } } else { // no websocket request => failure _logger.LogWarning("OCPPMiddleware => Non-Websocket request"); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; } } else { // unknown chargepoint _logger.LogTrace("OCPPMiddleware => no chargepoint: http 412"); context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed; } } else if (context.Request.Path.StartsWithSegments("/API")) { // Check authentication (X-API-Key) string apiKeyConfig = _configuration.GetValue <string>("ApiKey"); if (!string.IsNullOrWhiteSpace(apiKeyConfig)) { // ApiKey specified => check request string apiKeyCaller = context.Request.Headers["X-API-Key"].FirstOrDefault(); if (apiKeyConfig == apiKeyCaller) { // API-Key matches _logger.LogInformation("OCPPMiddleware => Success: X-API-Key matches"); } else { // API-Key does NOT matches => authentication failure!!! _logger.LogWarning("OCPPMiddleware => Failure: Wrong X-API-Key! Caller='{0}'", apiKeyCaller); context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; return; } } else { // No API-Key configured => no authenticatiuon _logger.LogWarning("OCPPMiddleware => No X-API-Key configured!"); } // format: /API/<command>[/chargepointId] string[] urlParts = context.Request.Path.Value.Split('/'); if (urlParts.Length >= 3) { string cmd = urlParts[2]; string urlChargePointId = (urlParts.Length >= 4) ? urlParts[3] : null; _logger.LogTrace("OCPPMiddleware => cmd='{0}' / id='{1}' / FullPath='{2}')", cmd, urlChargePointId, context.Request.Path.Value); if (cmd == "Status") { try { List <ChargePointStatus> statusList = new List <ChargePointStatus>(); foreach (ChargePointStatus status in _chargePointStatusDict.Values) { statusList.Add(status); } string jsonStatus = JsonConvert.SerializeObject(statusList); context.Response.ContentType = "application/json"; await context.Response.WriteAsync(jsonStatus); } catch (Exception exp) { _logger.LogError(exp, "OCPPMiddleware => Error: {0}", exp.Message); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } } else if (cmd == "Reset") { if (!string.IsNullOrEmpty(urlChargePointId)) { try { ChargePointStatus status = null; if (_chargePointStatusDict.TryGetValue(urlChargePointId, out status)) { // Send message to chargepoint if (status.Protocol == Protocol_OCPP20) { // OCPP V2.0 await Reset20(status, context); } else { // OCPP V1.6 await Reset16(status, context); } } else { // Chargepoint offline _logger.LogError("OCPPMiddleware SoftReset => Chargepoint offline: {0}", urlChargePointId); context.Response.StatusCode = (int)HttpStatusCode.NotFound; } } catch (Exception exp) { _logger.LogError(exp, "OCPPMiddleware SoftReset => Error: {0}", exp.Message); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } } else { _logger.LogError("OCPPMiddleware SoftReset => Missing chargepoint ID"); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; } } else if (cmd == "UnlockConnector") { if (!string.IsNullOrEmpty(urlChargePointId)) { try { ChargePointStatus status = null; if (_chargePointStatusDict.TryGetValue(urlChargePointId, out status)) { // Send message to chargepoint if (status.Protocol == Protocol_OCPP20) { // OCPP V2.0 await UnlockConnector20(status, context); } else { // OCPP V1.6 await UnlockConnector16(status, context); } } else { // Chargepoint offline _logger.LogError("OCPPMiddleware UnlockConnector => Chargepoint offline: {0}", urlChargePointId); context.Response.StatusCode = (int)HttpStatusCode.NotFound; } } catch (Exception exp) { _logger.LogError(exp, "OCPPMiddleware UnlockConnector => Error: {0}", exp.Message); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } } else { _logger.LogError("OCPPMiddleware UnlockConnector => Missing chargepoint ID"); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; } } else { // Unknown action/function _logger.LogWarning("OCPPMiddleware => action/function: {0}", cmd); context.Response.StatusCode = (int)HttpStatusCode.NotFound; } } } else if (context.Request.Path.StartsWithSegments("/")) { try { bool showIndexInfo = _configuration.GetValue <bool>("ShowIndexInfo"); if (showIndexInfo) { _logger.LogTrace("OCPPMiddleware => Index status page"); context.Response.ContentType = "text/plain"; await context.Response.WriteAsync(string.Format("Running...\r\n\r\n{0} chargepoints connected", _chargePointStatusDict.Values.Count)); } else { _logger.LogInformation("OCPPMiddleware => Root path with deactivated index page"); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; } } catch (Exception exp) { _logger.LogError(exp, "OCPPMiddleware => Error: {0}", exp.Message); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } } else { _logger.LogWarning("OCPPMiddleware => Bad path request"); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; } }
public IActionResult ChargePoint(string Id, ChargePointViewModel cpvm) { try { if (User != null && !User.IsInRole(Constants.AdminRoleName)) { Logger.LogWarning("ChargePoint: Request by non-administrator: {0}", User?.Identity?.Name); TempData["ErrMsgKey"] = "AccessDenied"; return(RedirectToAction("Error", new { Id = "" })); } cpvm.CurrentId = Id; using (OCPPCoreContext dbContext = new OCPPCoreContext(this.Config)) { Logger.LogTrace("ChargePoint: Loading charge points..."); List <ChargePoint> dbChargePoints = dbContext.ChargePoints.ToList <ChargePoint>(); Logger.LogInformation("ChargePoint: Found {0} charge points", dbChargePoints.Count); ChargePoint currentChargePoint = null; if (!string.IsNullOrEmpty(Id)) { foreach (ChargePoint cp in dbChargePoints) { if (cp.ChargePointId.Equals(Id, StringComparison.InvariantCultureIgnoreCase)) { currentChargePoint = cp; Logger.LogTrace("ChargePoint: Current charge point: {0} / {1}", cp.ChargePointId, cp.Name); break; } } } if (Request.Method == "POST") { string errorMsg = null; if (Id == "@") { Logger.LogTrace("ChargePoint: Creating new charge point..."); // Create new tag if (string.IsNullOrWhiteSpace(cpvm.ChargePointId)) { errorMsg = _localizer["ChargePointIdRequired"].Value; Logger.LogInformation("ChargePoint: New => no charge point ID entered"); } if (string.IsNullOrEmpty(errorMsg)) { // check if duplicate foreach (ChargePoint cp in dbChargePoints) { if (cp.ChargePointId.Equals(cpvm.ChargePointId, StringComparison.InvariantCultureIgnoreCase)) { // id already exists errorMsg = _localizer["ChargePointIdExists"].Value; Logger.LogInformation("ChargePoint: New => charge point ID already exists: {0}", cpvm.ChargePointId); break; } } } if (string.IsNullOrEmpty(errorMsg)) { // Save tag in DB ChargePoint newChargePoint = new ChargePoint(); newChargePoint.ChargePointId = cpvm.ChargePointId; newChargePoint.Name = cpvm.Name; newChargePoint.Comment = cpvm.Comment; newChargePoint.Username = cpvm.Username; newChargePoint.Password = cpvm.Password; newChargePoint.ClientCertThumb = cpvm.ClientCertThumb; dbContext.ChargePoints.Add(newChargePoint); dbContext.SaveChanges(); Logger.LogInformation("ChargePoint: New => charge point saved: {0} / {1}", cpvm.ChargePointId, cpvm.Name); } else { ViewBag.ErrorMsg = errorMsg; return(View("ChargePointDetail", cpvm)); } } else if (currentChargePoint.ChargePointId == Id) { // Save existing charge point Logger.LogTrace("ChargePoint: Saving charge point '{0}'", Id); currentChargePoint.Name = cpvm.Name; currentChargePoint.Comment = cpvm.Comment; currentChargePoint.Username = cpvm.Username; currentChargePoint.Password = cpvm.Password; currentChargePoint.ClientCertThumb = cpvm.ClientCertThumb; dbContext.SaveChanges(); Logger.LogInformation("ChargePoint: Edit => charge point saved: {0} / {1}", cpvm.ChargePointId, cpvm.Name); } return(RedirectToAction("ChargePoint", new { Id = "" })); } else { // Display charge point cpvm = new ChargePointViewModel(); cpvm.ChargePoints = dbChargePoints; cpvm.CurrentId = Id; if (currentChargePoint != null) { cpvm = new ChargePointViewModel(); cpvm.ChargePointId = currentChargePoint.ChargePointId; cpvm.Name = currentChargePoint.Name; cpvm.Comment = currentChargePoint.Comment; cpvm.Username = currentChargePoint.Username; cpvm.Password = currentChargePoint.Password; cpvm.ClientCertThumb = currentChargePoint.ClientCertThumb; } string viewName = (!string.IsNullOrEmpty(cpvm.ChargePointId) || Id == "@") ? "ChargePointDetail" : "ChargePointList"; return(View(viewName, cpvm)); } } } catch (Exception exp) { Logger.LogError(exp, "ChargePoint: Error loading charge points from database"); TempData["ErrMessage"] = exp.Message; return(RedirectToAction("Error", new { Id = "" })); } }
public async Task <IActionResult> Reset(string Id) { if (User != null && !User.IsInRole(Constants.AdminRoleName)) { Logger.LogWarning("Reset: Request by non-administrator: {0}", User?.Identity?.Name); return(StatusCode((int)HttpStatusCode.Unauthorized)); } int httpStatuscode = (int)HttpStatusCode.OK; string resultContent = string.Empty; Logger.LogTrace("Reset: Request to restart chargepoint '{0}'", Id); if (!string.IsNullOrEmpty(Id)) { try { using (OCPPCoreContext dbContext = new OCPPCoreContext(this.Config)) { ChargePoint chargePoint = dbContext.ChargePoints.Find(Id); if (chargePoint != null) { string serverApiUrl = base.Config.GetValue <string>("ServerApiUrl"); string apiKeyConfig = base.Config.GetValue <string>("ApiKey"); if (!string.IsNullOrEmpty(serverApiUrl)) { try { using (var httpClient = new HttpClient()) { if (!serverApiUrl.EndsWith('/')) { serverApiUrl += "/"; } Uri uri = new Uri(serverApiUrl); uri = new Uri(uri, $"Reset/{Uri.EscapeUriString(Id)}"); httpClient.Timeout = new TimeSpan(0, 0, 4); // use short timeout // API-Key authentication? if (!string.IsNullOrWhiteSpace(apiKeyConfig)) { httpClient.DefaultRequestHeaders.Add("X-API-Key", apiKeyConfig); } else { Logger.LogWarning("Reset: No API-Key configured!"); } HttpResponseMessage response = await httpClient.GetAsync(uri); if (response.StatusCode == HttpStatusCode.OK) { string jsonResult = await response.Content.ReadAsStringAsync(); if (!string.IsNullOrEmpty(jsonResult)) { try { dynamic jsonObject = JsonConvert.DeserializeObject(jsonResult); Logger.LogInformation("Reset: Result of API request is '{0}'", jsonResult); string status = jsonObject.status; switch (status) { case "Accepted": resultContent = _localizer["ResetAccepted"]; break; case "Rejected": resultContent = _localizer["ResetRejected"]; break; case "Scheduled": resultContent = _localizer["ResetScheduled"]; break; default: resultContent = string.Format(_localizer["ResetUnknownStatus"], status); break; } } catch (Exception exp) { Logger.LogError(exp, "Reset: Error in JSON result => {0}", exp.Message); httpStatuscode = (int)HttpStatusCode.OK; resultContent = _localizer["ResetError"]; } } else { Logger.LogError("Reset: Result of API request is empty"); httpStatuscode = (int)HttpStatusCode.OK; resultContent = _localizer["ResetError"]; } } else if (response.StatusCode == HttpStatusCode.NotFound) { // Chargepoint offline httpStatuscode = (int)HttpStatusCode.OK; resultContent = _localizer["ResetOffline"]; } else { Logger.LogError("Reset: Result of API request => httpStatus={0}", response.StatusCode); httpStatuscode = (int)HttpStatusCode.OK; resultContent = _localizer["ResetError"]; } } } catch (Exception exp) { Logger.LogError(exp, "Reset: Error in API request => {0}", exp.Message); httpStatuscode = (int)HttpStatusCode.OK; resultContent = _localizer["ResetError"]; } } } else { Logger.LogWarning("Reset: Error loading charge point '{0}' from database", Id); httpStatuscode = (int)HttpStatusCode.OK; resultContent = _localizer["UnknownChargepoint"]; } } } catch (Exception exp) { Logger.LogError(exp, "Reset: Error loading charge point from database"); httpStatuscode = (int)HttpStatusCode.OK; resultContent = _localizer["ResetError"]; } } return(StatusCode(httpStatuscode, resultContent)); }
public IActionResult ChargeTag(string Id, ChargeTagViewModel ctvm) { try { if (User != null && !User.IsInRole(Constants.AdminRoleName)) { Logger.LogWarning("ChargeTag: Request by non-administrator: {0}", User?.Identity?.Name); TempData["ErrMsgKey"] = "AccessDenied"; return(RedirectToAction("Error", new { Id = "" })); } ViewBag.DatePattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern; ViewBag.Language = CultureInfo.CurrentCulture.TwoLetterISOLanguageName; ctvm.CurrentTagId = Id; using (OCPPCoreContext dbContext = new OCPPCoreContext(this.Config)) { Logger.LogTrace("ChargeTag: Loading charge tags..."); List <ChargeTag> dbChargeTags = dbContext.ChargeTags.ToList <ChargeTag>(); Logger.LogInformation("ChargeTag: Found {0} charge tags", dbChargeTags.Count); ChargeTag currentChargeTag = null; if (!string.IsNullOrEmpty(Id)) { foreach (ChargeTag tag in dbChargeTags) { if (tag.TagId.Equals(Id, StringComparison.InvariantCultureIgnoreCase)) { currentChargeTag = tag; Logger.LogTrace("ChargeTag: Current charge tag: {0} / {1}", tag.TagId, tag.TagName); break; } } } if (Request.Method == "POST") { string errorMsg = null; if (Id == "@") { Logger.LogTrace("ChargeTag: Creating new charge tag..."); // Create new tag if (string.IsNullOrWhiteSpace(ctvm.TagId)) { errorMsg = _localizer["ChargeTagIdRequired"].Value; Logger.LogInformation("ChargeTag: New => no charge tag ID entered"); } if (string.IsNullOrEmpty(errorMsg)) { // check if duplicate foreach (ChargeTag tag in dbChargeTags) { if (tag.TagId.Equals(ctvm.TagId, StringComparison.InvariantCultureIgnoreCase)) { // tag-id already exists errorMsg = _localizer["ChargeTagIdExists"].Value; Logger.LogInformation("ChargeTag: New => charge tag ID already exists: {0}", ctvm.TagId); break; } } } if (string.IsNullOrEmpty(errorMsg)) { // Save tag in DB ChargeTag newTag = new ChargeTag(); newTag.TagId = ctvm.TagId; newTag.TagName = ctvm.TagName; newTag.ParentTagId = ctvm.ParentTagId; newTag.ExpiryDate = ctvm.ExpiryDate; newTag.Blocked = ctvm.Blocked; dbContext.ChargeTags.Add(newTag); dbContext.SaveChanges(); Logger.LogInformation("ChargeTag: New => charge tag saved: {0} / {1}", ctvm.TagId, ctvm.TagName); } else { ViewBag.ErrorMsg = errorMsg; return(View("ChargeTagDetail", ctvm)); } } else if (currentChargeTag.TagId == Id) { // Save existing tag currentChargeTag.TagName = ctvm.TagName; currentChargeTag.ParentTagId = ctvm.ParentTagId; currentChargeTag.ExpiryDate = ctvm.ExpiryDate; currentChargeTag.Blocked = ctvm.Blocked; dbContext.SaveChanges(); Logger.LogInformation("ChargeTag: Edit => charge tag saved: {0} / {1}", ctvm.TagId, ctvm.TagName); } return(RedirectToAction("ChargeTag", new { Id = "" })); } else { // List all charge tags ctvm = new ChargeTagViewModel(); ctvm.ChargeTags = dbChargeTags; ctvm.CurrentTagId = Id; if (currentChargeTag != null) { ctvm.TagId = currentChargeTag.TagId; ctvm.TagName = currentChargeTag.TagName; ctvm.ParentTagId = currentChargeTag.ParentTagId; ctvm.ExpiryDate = currentChargeTag.ExpiryDate; ctvm.Blocked = (currentChargeTag.Blocked != null) && currentChargeTag.Blocked.Value; } string viewName = (!string.IsNullOrEmpty(ctvm.TagId) || Id == "@") ? "ChargeTagDetail" : "ChargeTagList"; return(View(viewName, ctvm)); } } } catch (Exception exp) { Logger.LogError(exp, "ChargeTag: Error loading charge tags from database"); TempData["ErrMessage"] = exp.Message; return(RedirectToAction("Error", new { Id = "" })); } }
public string HandleStopTransaction(OCPPMessage msgIn, OCPPMessage msgOut) { string errorCode = null; StopTransactionResponse stopTransactionResponse = new StopTransactionResponse(); try { Logger.LogTrace("Processing stopTransaction request..."); StopTransactionRequest stopTransactionRequest = JsonConvert.DeserializeObject <StopTransactionRequest>(msgIn.JsonPayload); Logger.LogTrace("StopTransaction => Message deserialized"); string idTag = Utils.CleanChargeTagId(stopTransactionRequest.IdTag, Logger); if (string.IsNullOrWhiteSpace(idTag)) { // no RFID-Tag => accept request stopTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Accepted; Logger.LogInformation("StopTransaction => no charge tag => Status: {0}", stopTransactionResponse.IdTagInfo.Status); } else { stopTransactionResponse.IdTagInfo = new IdTagInfo(); stopTransactionResponse.IdTagInfo.ExpiryDate = Utils.MaxExpiryDate; try { using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { ChargeTag ct = dbContext.Find <ChargeTag>(idTag); if (ct != null) { if (ct.ExpiryDate.HasValue) { stopTransactionResponse.IdTagInfo.ExpiryDate = ct.ExpiryDate.Value; } stopTransactionResponse.IdTagInfo.ParentIdTag = ct.ParentTagId; if (ct.Blocked.HasValue && ct.Blocked.Value) { stopTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Blocked; } else if (ct.ExpiryDate.HasValue && ct.ExpiryDate.Value < DateTime.Now) { stopTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Expired; } else { stopTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Accepted; } } else { stopTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Invalid; } Logger.LogInformation("StopTransaction => RFID-tag='{0}' => Status: {1}", idTag, stopTransactionResponse.IdTagInfo.Status); } } catch (Exception exp) { Logger.LogError(exp, "StopTransaction => Exception reading charge tag ({0}): {1}", idTag, exp.Message); stopTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Invalid; } } if (stopTransactionResponse.IdTagInfo.Status == IdTagInfoStatus.Accepted) { try { using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { Transaction transaction = dbContext.Find <Transaction>(stopTransactionRequest.TransactionId); if (transaction == null || transaction.ChargePointId != ChargePointStatus.Id || transaction.StopTime.HasValue) { // unknown transaction id or already stopped transaction // => find latest transaction for the charge point and check if its open Logger.LogWarning("StopTransaction => Unknown or closed transaction id={0}", transaction?.TransactionId); transaction = dbContext.Transactions .Where(t => t.ChargePointId == ChargePointStatus.Id) .OrderByDescending(t => t.TransactionId) .FirstOrDefault(); if (transaction != null) { Logger.LogTrace("StopTransaction => Last transaction id={0} / Start='{1}' / Stop='{2}'", transaction.TransactionId, transaction.StartTime.ToString("O"), transaction?.StopTime?.ToString("o")); if (transaction.StopTime.HasValue) { Logger.LogTrace("StopTransaction => Last transaction (id={0}) is already closed ", transaction.TransactionId); transaction = null; } } else { Logger.LogTrace("StopTransaction => Found no transaction for charge point '{0}'", ChargePointStatus.Id); } } if (transaction != null) { // check current tag against start tag bool valid = true; if (!string.Equals(transaction.StartTagId, idTag, StringComparison.InvariantCultureIgnoreCase)) { // tags are different => same group? ChargeTag startTag = dbContext.Find <ChargeTag>(transaction.StartTagId); if (startTag != null) { if (!string.Equals(startTag.ParentTagId, stopTransactionResponse.IdTagInfo.ParentIdTag, StringComparison.InvariantCultureIgnoreCase)) { Logger.LogInformation("StopTransaction => Start-Tag ('{0}') and End-Tag ('{1}') do not match: Invalid!", transaction.StartTagId, idTag); stopTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Invalid; valid = false; } else { Logger.LogInformation("StopTransaction => Different RFID-Tags but matching group ('{0}')", stopTransactionResponse.IdTagInfo.ParentIdTag); } } else { Logger.LogError("StopTransaction => Start-Tag not found: '{0}'", transaction.StartTagId); // assume "valid" and allow to end the transaction } } if (valid) { transaction.StopTagId = idTag; transaction.MeterStop = (double)stopTransactionRequest.MeterStop / 1000; // Meter value here is always Wh transaction.StopReason = stopTransactionRequest.Reason.ToString(); transaction.StopTime = stopTransactionRequest.Timestamp.UtcDateTime; dbContext.SaveChanges(); } } else { Logger.LogError("StopTransaction => Unknown transaction: id={0} / chargepoint={1} / tag={2}", stopTransactionRequest.TransactionId, ChargePointStatus?.Id, idTag); WriteMessageLog(ChargePointStatus?.Id, transaction?.ConnectorId, msgIn.Action, string.Format("UnknownTransaction:ID={0}/Meter={1}", stopTransactionRequest.TransactionId, stopTransactionRequest.MeterStop), errorCode); errorCode = ErrorCodes.PropertyConstraintViolation; } } } catch (Exception exp) { Logger.LogError(exp, "StopTransaction => Exception writing transaction: chargepoint={0} / tag={1}", ChargePointStatus?.Id, idTag); errorCode = ErrorCodes.InternalError; } } msgOut.JsonPayload = JsonConvert.SerializeObject(stopTransactionResponse); Logger.LogTrace("StopTransaction => Response serialized"); } catch (Exception exp) { Logger.LogError(exp, "StopTransaction => Exception: {0}", exp.Message); errorCode = ErrorCodes.FormationViolation; } WriteMessageLog(ChargePointStatus?.Id, null, msgIn.Action, stopTransactionResponse.IdTagInfo?.Status.ToString(), errorCode); return(errorCode); }
public string HandleStartTransaction(OCPPMessage msgIn, OCPPMessage msgOut) { string errorCode = null; StartTransactionResponse startTransactionResponse = new StartTransactionResponse(); int?connectorId = null; try { Logger.LogTrace("Processing startTransaction request..."); StartTransactionRequest startTransactionRequest = JsonConvert.DeserializeObject <StartTransactionRequest>(msgIn.JsonPayload); Logger.LogTrace("StartTransaction => Message deserialized"); string idTag = Utils.CleanChargeTagId(startTransactionRequest.IdTag, Logger); connectorId = startTransactionRequest.ConnectorId; startTransactionResponse.IdTagInfo.ParentIdTag = string.Empty; startTransactionResponse.IdTagInfo.ExpiryDate = Utils.MaxExpiryDate; if (string.IsNullOrWhiteSpace(idTag)) { // no RFID-Tag => accept request startTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Accepted; Logger.LogInformation("StartTransaction => no charge tag => Status: {0}", startTransactionResponse.IdTagInfo.Status); } else { try { using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { ChargeTag ct = dbContext.Find <ChargeTag>(idTag); if (ct != null) { if (ct.ExpiryDate.HasValue) { startTransactionResponse.IdTagInfo.ExpiryDate = ct.ExpiryDate.Value; } startTransactionResponse.IdTagInfo.ParentIdTag = ct.ParentTagId; if (ct.Blocked.HasValue && ct.Blocked.Value) { startTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Blocked; } else if (ct.ExpiryDate.HasValue && ct.ExpiryDate.Value < DateTime.Now) { startTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Expired; } else { startTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Accepted; } } else { startTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Invalid; } Logger.LogInformation("StartTransaction => Charge tag='{0}' => Status: {1}", idTag, startTransactionResponse.IdTagInfo.Status); } } catch (Exception exp) { Logger.LogError(exp, "StartTransaction => Exception reading charge tag ({0}): {1}", idTag, exp.Message); startTransactionResponse.IdTagInfo.Status = IdTagInfoStatus.Invalid; } } if (startTransactionResponse.IdTagInfo.Status == IdTagInfoStatus.Accepted) { try { using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { Transaction transaction = new Transaction(); transaction.ChargePointId = ChargePointStatus?.Id; transaction.ConnectorId = startTransactionRequest.ConnectorId; transaction.StartTagId = idTag; transaction.StartTime = startTransactionRequest.Timestamp.UtcDateTime; transaction.MeterStart = (double)startTransactionRequest.MeterStart / 1000; // Meter value here is always Wh transaction.StartResult = startTransactionResponse.IdTagInfo.Status.ToString(); dbContext.Add <Transaction>(transaction); dbContext.SaveChanges(); // Return DB-ID as transaction ID startTransactionResponse.TransactionId = transaction.TransactionId; } } catch (Exception exp) { Logger.LogError(exp, "StartTransaction => Exception writing transaction: chargepoint={0} / tag={1}", ChargePointStatus?.Id, idTag); errorCode = ErrorCodes.InternalError; } } msgOut.JsonPayload = JsonConvert.SerializeObject(startTransactionResponse); Logger.LogTrace("StartTransaction => Response serialized"); } catch (Exception exp) { Logger.LogError(exp, "StartTransaction => Exception: {0}", exp.Message); errorCode = ErrorCodes.FormationViolation; } WriteMessageLog(ChargePointStatus?.Id, connectorId, msgIn.Action, startTransactionResponse.IdTagInfo?.Status.ToString(), errorCode); return(errorCode); }
public string HandleAuthorize(OCPPMessage msgIn, OCPPMessage msgOut) { string errorCode = null; AuthorizeResponse authorizeResponse = new AuthorizeResponse(); string idTag = null; try { Logger.LogTrace("Processing authorize request..."); AuthorizeRequest authorizeRequest = JsonConvert.DeserializeObject <AuthorizeRequest>(msgIn.JsonPayload); Logger.LogTrace("Authorize => Message deserialized"); idTag = Utils.CleanChargeTagId(authorizeRequest.IdToken?.IdToken, Logger); authorizeResponse.CustomData = new CustomDataType(); authorizeResponse.CustomData.VendorId = VendorId; authorizeResponse.IdTokenInfo = new IdTokenInfoType(); authorizeResponse.IdTokenInfo.CustomData = new CustomDataType(); authorizeResponse.IdTokenInfo.CustomData.VendorId = VendorId; authorizeResponse.IdTokenInfo.GroupIdToken = new IdTokenType(); authorizeResponse.IdTokenInfo.GroupIdToken.CustomData = new CustomDataType(); authorizeResponse.IdTokenInfo.GroupIdToken.CustomData.VendorId = VendorId; authorizeResponse.IdTokenInfo.GroupIdToken.IdToken = string.Empty; try { using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { ChargeTag ct = dbContext.Find <ChargeTag>(idTag); if (ct != null) { if (!string.IsNullOrEmpty(ct.ParentTagId)) { authorizeResponse.IdTokenInfo.GroupIdToken.IdToken = ct.ParentTagId; } if (ct.Blocked.HasValue && ct.Blocked.Value) { authorizeResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Blocked; } else if (ct.ExpiryDate.HasValue && ct.ExpiryDate.Value < DateTime.Now) { authorizeResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Expired; } else { authorizeResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Accepted; } } else { authorizeResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Invalid; } Logger.LogInformation("Authorize => Status: {0}", authorizeResponse.IdTokenInfo.Status); } } catch (Exception exp) { Logger.LogError(exp, "Authorize => Exception reading charge tag ({0}): {1}", idTag, exp.Message); authorizeResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Invalid; } msgOut.JsonPayload = JsonConvert.SerializeObject(authorizeResponse); Logger.LogTrace("Authorize => Response serialized"); } catch (Exception exp) { Logger.LogError(exp, "Authorize => Exception: {0}", exp.Message); errorCode = ErrorCodes.FormationViolation; } WriteMessageLog(ChargePointStatus?.Id, null, msgIn.Action, $"'{idTag}'=>{authorizeResponse.IdTokenInfo?.Status}", errorCode); return(errorCode); }
public IActionResult Transactions(string Id) { Logger.LogTrace("Transactions: Loading charge point transactions..."); TransactionListViewModel tlvm = new TransactionListViewModel(); tlvm.CurrentChargePointId = Id; tlvm.ChargePoints = new List <ChargePoint>(); tlvm.Transactions = new List <Transaction>(); try { string ts = Request.Query["t"]; int days = 30; if (ts == "2") { // 90 days days = 90; tlvm.Timespan = 2; } else if (ts == "3") { // 365 days days = 365; tlvm.Timespan = 3; } else { // 30 days days = 30; tlvm.Timespan = 1; } using (OCPPCoreContext dbContext = new OCPPCoreContext(this.Config)) { Logger.LogTrace("Transactions: Loading charge points..."); tlvm.ChargePoints = dbContext.ChargePoints.ToList <ChargePoint>(); // search selected charge point foreach (ChargePoint cp in tlvm.ChargePoints) { if (cp.ChargePointId == Id) { tlvm.CurrentChargePointName = cp.Name; if (string.IsNullOrEmpty(tlvm.CurrentChargePointName)) { tlvm.CurrentChargePointName = Id; } break; } } // load charge tags for name resolution Logger.LogTrace("Transactions: Loading charge tags..."); List <ChargeTag> chargeTags = dbContext.ChargeTags.ToList <ChargeTag>(); tlvm.ChargeTags = new Dictionary <string, ChargeTag>(); if (chargeTags != null) { foreach (ChargeTag tag in chargeTags) { tlvm.ChargeTags.Add(tag.TagId, tag); } } if (!string.IsNullOrEmpty(tlvm.CurrentChargePointId)) { Logger.LogTrace("Transactions: Loading charge point transactions..."); tlvm.Transactions = dbContext.Transactions .Where(t => t.ChargePointId == tlvm.CurrentChargePointId && t.StartTime >= DateTime.UtcNow.AddDays(-1 * days)) .OrderByDescending(t => t.TransactionId) .ToList <Transaction>(); } } } catch (Exception exp) { Logger.LogError(exp, "Transactions: Error loading charge points from database"); } return(View(tlvm)); }
public string HandleTransactionEvent(OCPPMessage msgIn, OCPPMessage msgOut) { string errorCode = null; TransactionEventResponse transactionEventResponse = new TransactionEventResponse(); transactionEventResponse.CustomData = new CustomDataType(); transactionEventResponse.CustomData.VendorId = VendorId; transactionEventResponse.IdTokenInfo = new IdTokenInfoType(); int connectorId = 0; try { Logger.LogTrace("TransactionEvent => Processing transactionEvent request..."); TransactionEventRequest transactionEventRequest = JsonConvert.DeserializeObject <TransactionEventRequest>(msgIn.JsonPayload); Logger.LogTrace("TransactionEvent => Message deserialized"); string idTag = Utils.CleanChargeTagId(transactionEventRequest.IdToken?.IdToken, Logger); connectorId = (transactionEventRequest.Evse != null) ? transactionEventRequest.Evse.ConnectorId : 0; if (transactionEventRequest.EventType == TransactionEventEnumType.Started) { try { #region Start Transaction using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { if (string.IsNullOrWhiteSpace(idTag)) { // no RFID-Tag => accept request transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Accepted; Logger.LogInformation("StartTransaction => no charge tag => accepted"); } else { ChargeTag ct = dbContext.Find <ChargeTag>(idTag); if (ct != null) { if (ct.Blocked.HasValue && ct.Blocked.Value) { Logger.LogInformation("StartTransaction => Tag '{1}' blocked)", idTag); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Blocked; } else if (ct.ExpiryDate.HasValue && ct.ExpiryDate.Value < DateTime.Now) { Logger.LogInformation("StartTransaction => Tag '{1}' expired)", idTag); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Expired; } else { Logger.LogInformation("StartTransaction => Tag '{1}' accepted)", idTag); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Accepted; } } else { Logger.LogInformation("StartTransaction => Tag '{1}' unknown)", idTag); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Unknown; } } if (transactionEventResponse.IdTokenInfo.Status == AuthorizationStatusEnumType.Accepted) { try { double meterKWH = GetMeterValue(transactionEventRequest.MeterValue); Logger.LogInformation("StartTransaction => Meter='{0}' (kWh)", meterKWH); Transaction transaction = new Transaction(); transaction.Uid = transactionEventRequest.TransactionInfo.TransactionId; transaction.ChargePointId = ChargePointStatus?.Id; transaction.ConnectorId = connectorId; transaction.StartTagId = idTag; transaction.StartTime = transactionEventRequest.Timestamp.UtcDateTime; transaction.MeterStart = meterKWH; transaction.StartResult = transactionEventRequest.TriggerReason.ToString(); dbContext.Add <Transaction>(transaction); dbContext.SaveChanges(); } catch (Exception exp) { Logger.LogError(exp, "StartTransaction => Exception writing transaction: chargepoint={0} / tag={1}", ChargePointStatus?.Id, idTag); errorCode = ErrorCodes.InternalError; } } } #endregion } catch (Exception exp) { Logger.LogError(exp, "StartTransaction => Exception: {0}", exp.Message); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Invalid; } } else if (transactionEventRequest.EventType == TransactionEventEnumType.Updated) { try { #region Update Transaction using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { Transaction transaction = dbContext.Transactions .Where(t => t.Uid == transactionEventRequest.TransactionInfo.TransactionId) .OrderByDescending(t => t.TransactionId) .FirstOrDefault(); if (transaction == null || transaction.ChargePointId != ChargePointStatus.Id || transaction.StopTime.HasValue) { // unknown transaction id or already stopped transaction // => find latest transaction for the charge point and check if its open Logger.LogWarning("UpdateTransaction => Unknown or closed transaction uid={0}", transactionEventRequest.TransactionInfo?.TransactionId); // find latest transaction for this charge point transaction = dbContext.Transactions .Where(t => t.ChargePointId == ChargePointStatus.Id && t.ConnectorId == connectorId) .OrderByDescending(t => t.TransactionId) .FirstOrDefault(); if (transaction != null) { Logger.LogTrace("UpdateTransaction => Last transaction id={0} / Start='{1}' / Stop='{2}'", transaction.TransactionId, transaction.StartTime.ToString("O"), transaction?.StopTime?.ToString("O")); if (transaction.StopTime.HasValue) { Logger.LogTrace("UpdateTransaction => Last transaction (id={0}) is already closed ", transaction.TransactionId); transaction = null; } } else { Logger.LogTrace("UpdateTransaction => Found no transaction for charge point '{0}' and connectorId '{1}'", ChargePointStatus.Id, connectorId); } } if (transaction != null) { // write current meter value in "stop" value double meterKWH = GetMeterValue(transactionEventRequest.MeterValue); Logger.LogInformation("UpdateTransaction => Meter='{0}' (kWh)", meterKWH); if (meterKWH >= 0) { transaction.MeterStop = meterKWH; dbContext.SaveChanges(); } } else { Logger.LogError("UpdateTransaction => Unknown transaction: uid='{0}' / chargepoint='{1}' / tag={2}", transactionEventRequest.TransactionInfo?.TransactionId, ChargePointStatus?.Id, idTag); WriteMessageLog(ChargePointStatus?.Id, null, msgIn.Action, string.Format("UnknownTransaction:UID={0}/Meter={1}", transactionEventRequest.TransactionInfo?.TransactionId, GetMeterValue(transactionEventRequest.MeterValue)), errorCode); errorCode = ErrorCodes.PropertyConstraintViolation; } } #endregion } catch (Exception exp) { Logger.LogError(exp, "UpdateTransaction => Exception: {0}", exp.Message); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Invalid; } } else if (transactionEventRequest.EventType == TransactionEventEnumType.Ended) { try { #region End Transaction using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { ChargeTag ct = null; if (string.IsNullOrWhiteSpace(idTag)) { // no RFID-Tag => accept request transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Accepted; Logger.LogInformation("EndTransaction => no charge tag => accepted"); } else { ct = dbContext.Find <ChargeTag>(idTag); if (ct != null) { if (ct.Blocked.HasValue && ct.Blocked.Value) { Logger.LogInformation("EndTransaction => Tag '{1}' blocked)", idTag); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Blocked; } else if (ct.ExpiryDate.HasValue && ct.ExpiryDate.Value < DateTime.Now) { Logger.LogInformation("EndTransaction => Tag '{1}' expired)", idTag); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Expired; } else { Logger.LogInformation("EndTransaction => Tag '{1}' accepted)", idTag); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Accepted; } } else { Logger.LogInformation("EndTransaction => Tag '{1}' unknown)", idTag); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Unknown; } } Transaction transaction = dbContext.Transactions .Where(t => t.Uid == transactionEventRequest.TransactionInfo.TransactionId) .OrderByDescending(t => t.TransactionId) .FirstOrDefault(); if (transaction == null || transaction.ChargePointId != ChargePointStatus.Id || transaction.StopTime.HasValue) { // unknown transaction id or already stopped transaction // => find latest transaction for the charge point and check if its open Logger.LogWarning("EndTransaction => Unknown or closed transaction uid={0}", transactionEventRequest.TransactionInfo?.TransactionId); // find latest transaction for this charge point transaction = dbContext.Transactions .Where(t => t.ChargePointId == ChargePointStatus.Id && t.ConnectorId == connectorId) .OrderByDescending(t => t.TransactionId) .FirstOrDefault(); if (transaction != null) { Logger.LogTrace("EndTransaction => Last transaction id={0} / Start='{1}' / Stop='{2}'", transaction.TransactionId, transaction.StartTime.ToString("O"), transaction?.StopTime?.ToString("O")); if (transaction.StopTime.HasValue) { Logger.LogTrace("EndTransaction => Last transaction (id={0}) is already closed ", transaction.TransactionId); transaction = null; } } else { Logger.LogTrace("EndTransaction => Found no transaction for charge point '{0}' and connectorId '{1}'", ChargePointStatus.Id, connectorId); } } if (transaction != null) { // check current tag against start tag bool valid = true; if (!string.Equals(transaction.StartTagId, idTag, StringComparison.InvariantCultureIgnoreCase)) { // tags are different => same group? ChargeTag startTag = dbContext.Find <ChargeTag>(transaction.StartTagId); if (startTag != null) { if (!string.Equals(startTag.ParentTagId, ct?.ParentTagId, StringComparison.InvariantCultureIgnoreCase)) { Logger.LogInformation("EndTransaction => Start-Tag ('{0}') and End-Tag ('{1}') do not match: Invalid!", transaction.StartTagId, ct?.TagId); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Invalid; valid = false; } else { Logger.LogInformation("EndTransaction => Different charge tags but matching group ('{0}')", ct?.ParentTagId); } } else { Logger.LogError("EndTransaction => Start-Tag not found: '{0}'", transaction.StartTagId); // assume "valid" and allow to end the transaction } } if (valid) { // write current meter value in "stop" value double meterKWH = GetMeterValue(transactionEventRequest.MeterValue); Logger.LogInformation("EndTransaction => Meter='{0}' (kWh)", meterKWH); transaction.StopTime = transactionEventRequest.Timestamp.UtcDateTime; transaction.MeterStop = meterKWH; transaction.StopTagId = idTag; transaction.StopReason = transactionEventRequest.TriggerReason.ToString(); dbContext.SaveChanges(); } } else { Logger.LogError("EndTransaction => Unknown transaction: uid='{0}' / chargepoint='{1}' / tag={2}", transactionEventRequest.TransactionInfo?.TransactionId, ChargePointStatus?.Id, idTag); WriteMessageLog(ChargePointStatus?.Id, connectorId, msgIn.Action, string.Format("UnknownTransaction:UID={0}/Meter={1}", transactionEventRequest.TransactionInfo?.TransactionId, GetMeterValue(transactionEventRequest.MeterValue)), errorCode); errorCode = ErrorCodes.PropertyConstraintViolation; } } #endregion } catch (Exception exp) { Logger.LogError(exp, "EndTransaction => Exception: {0}", exp.Message); transactionEventResponse.IdTokenInfo.Status = AuthorizationStatusEnumType.Invalid; } } msgOut.JsonPayload = JsonConvert.SerializeObject(transactionEventResponse); Logger.LogTrace("TransactionEvent => Response serialized"); } catch (Exception exp) { Logger.LogError(exp, "TransactionEvent => Exception: {0}", exp.Message); errorCode = ErrorCodes.FormationViolation; } WriteMessageLog(ChargePointStatus?.Id, connectorId, msgIn.Action, transactionEventResponse.IdTokenInfo.Status.ToString(), errorCode); return(errorCode); }
public string HandleAuthorize(OCPPMessage msgIn, OCPPMessage msgOut) { string errorCode = null; AuthorizeResponse authorizeResponse = new AuthorizeResponse(); string idTag = null; try { Logger.LogTrace("Processing authorize request..."); AuthorizeRequest authorizeRequest = JsonConvert.DeserializeObject <AuthorizeRequest>(msgIn.JsonPayload); Logger.LogTrace("Authorize => Message deserialized"); idTag = Utils.CleanChargeTagId(authorizeRequest.IdTag, Logger); authorizeResponse.IdTagInfo.ParentIdTag = string.Empty; authorizeResponse.IdTagInfo.ExpiryDate = DateTimeOffset.UtcNow.AddMinutes(5); // default: 5 minutes try { using (OCPPCoreContext dbContext = new OCPPCoreContext(Configuration)) { ChargeTag ct = dbContext.Find <ChargeTag>(idTag); if (ct != null) { if (ct.ExpiryDate.HasValue) { authorizeResponse.IdTagInfo.ExpiryDate = ct.ExpiryDate.Value; } authorizeResponse.IdTagInfo.ParentIdTag = ct.ParentTagId; if (ct.Blocked.HasValue && ct.Blocked.Value) { authorizeResponse.IdTagInfo.Status = IdTagInfoStatus.Blocked; } else if (ct.ExpiryDate.HasValue && ct.ExpiryDate.Value < DateTime.Now) { authorizeResponse.IdTagInfo.Status = IdTagInfoStatus.Expired; } else { authorizeResponse.IdTagInfo.Status = IdTagInfoStatus.Accepted; } } else { authorizeResponse.IdTagInfo.Status = IdTagInfoStatus.Invalid; } Logger.LogInformation("Authorize => Status: {0}", authorizeResponse.IdTagInfo.Status); } } catch (Exception exp) { Logger.LogError(exp, "Authorize => Exception reading charge tag ({0}): {1}", idTag, exp.Message); authorizeResponse.IdTagInfo.Status = IdTagInfoStatus.Invalid; } msgOut.JsonPayload = JsonConvert.SerializeObject(authorizeResponse); Logger.LogTrace("Authorize => Response serialized"); } catch (Exception exp) { Logger.LogError(exp, "Authorize => Exception: {0}", exp.Message); errorCode = ErrorCodes.FormationViolation; } WriteMessageLog(ChargePointStatus?.Id, null, msgIn.Action, $"'{idTag}'=>{authorizeResponse.IdTagInfo?.Status}", errorCode); return(errorCode); }
public IActionResult Export(string Id) { Logger.LogTrace("Export: Loading charge point transactions..."); TransactionListViewModel tlvm = new TransactionListViewModel(); tlvm.CurrentChargePointId = Id; tlvm.ChargePoints = new List <ChargePoint>(); tlvm.Transactions = new List <Transaction>(); try { string ts = Request.Query["t"]; int days = 30; if (ts == "2") { // 90 days days = 90; tlvm.Timespan = 2; } else if (ts == "3") { // 365 days days = 365; tlvm.Timespan = 3; } else { // 30 days days = 30; tlvm.Timespan = 1; } using (OCPPCoreContext dbContext = new OCPPCoreContext(this.Config)) { Logger.LogTrace("Export: Loading charge points..."); tlvm.ChargePoints = dbContext.ChargePoints.ToList <ChargePoint>(); foreach (ChargePoint cp in tlvm.ChargePoints) { if (cp.ChargePointId == Id) { tlvm.CurrentChargePointName = cp.Name; if (string.IsNullOrEmpty(tlvm.CurrentChargePointName)) { tlvm.CurrentChargePointName = Id; } break; } } // load charge tags for name resolution Logger.LogTrace("Export: Loading charge tags..."); tlvm.ChargePoints = dbContext.ChargePoints.ToList <ChargePoint>(); List <ChargeTag> chargeTags = dbContext.ChargeTags.ToList <ChargeTag>(); tlvm.ChargeTags = new Dictionary <string, ChargeTag>(); if (chargeTags != null) { foreach (ChargeTag tag in chargeTags) { tlvm.ChargeTags.Add(tag.TagId, tag); } } if (!string.IsNullOrEmpty(tlvm.CurrentChargePointId)) { Logger.LogTrace("Export: Loading charge point transactions..."); tlvm.Transactions = dbContext.Transactions .Where(t => t.ChargePointId == tlvm.CurrentChargePointId && t.StartTime >= DateTime.UtcNow.AddDays(-1 * days)) .OrderByDescending(t => t.TransactionId) .ToList <Transaction>(); } StringBuilder chargepointName = new StringBuilder(tlvm.CurrentChargePointName); foreach (char c in Path.GetInvalidFileNameChars()) { chargepointName.Replace(c, '_'); } string filename = string.Format("Transactions_{0}.csv", chargepointName); string csv = CreateCsv(tlvm); Logger.LogInformation("Export: File => {0} Chars / Name '{1}'", csv.Length, filename); return(File(Encoding.GetEncoding("ISO-8859-1").GetBytes(csv), "text/csv", filename)); } } catch (Exception exp) { Logger.LogError(exp, "Export: Error loading charge points from database"); } return(View(tlvm)); }