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 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); }