using EVCB_OCPP.Packet.Features; using EVCB_OCPP.Packet.Messages; using OCPPServer.Protocol; using System; using Microsoft.Extensions.Logging; using EVCB_OCPP.WSServer.Service.WsService; using EVCB_OCPP.Packet.Messages.Security; using Microsoft.EntityFrameworkCore; namespace EVCB_OCPP.WSServer.Message { internal partial class ProfileHandler { internal async Task ExecuteSecurityRequest(Actions action, WsClientData session, IRequest request) { MessageResult result = new MessageResult() { Success = false }; try { switch (action) { case Actions.SignCertificate: { SignCertificateRequest _request = request as SignCertificateRequest; SignCertificateConfirmation confirm = new(); if (string.IsNullOrEmpty(_request.csr)) { result.Success = false; return result; } bool isCsrValid = CheckCsr(session.ChargeBoxId, _request.csr); if (!isCsrValid) { confirm.status = Packet.Messages.SubTypes.GenericStatusEnumType.Rejected; result.Message = confirm; result.Success = false; return result; } _ = certService.SignCertificate(session.ChargeBoxId, _request.csr); confirm.status = Packet.Messages.SubTypes.GenericStatusEnumType.Accepted; result.Message = confirm; result.Success = true; return result; } case Actions.SecurityEventNotification: { SecurityEventNotificationRequest _request = request as SecurityEventNotificationRequest; SecurityEventNotificationConfirmation confirm = new(); logger.LogInformation("{chargeBoxId} security notification {sects} {sectype} {secmsg}", session.ChargeBoxId, _request.timestamp, _request.type, _request.techInfo); result.Message = confirm; result.Success = true; return result; } case Actions.LogStatusNotification: { LogStatusNotificationRequest _request = request as LogStatusNotificationRequest; LogStatusNotificationConfirmation confirm = new(); if (_request.status != Packet.Messages.SubTypes.UploadLogStatusEnumType.Idle) { using (var db = await maindbContextFactory.CreateDbContextAsync()) { var item = await db.MachineOperateRecord.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.Action == "GetLog" && x.RequestType == 1) .OrderByDescending(x => x.CreatedOn).FirstOrDefaultAsync(); if (item != null) { item.EVSE_Status = (int)_request.status; item.FinishedOn = DateTime.UtcNow; } await db.SaveChangesAsync(); } } result.Message = confirm; result.Success = true; return result; } case Actions.SignedFirmwareStatusNotification: { SignedFirmwareStatusNotificationRequest _request = request as SignedFirmwareStatusNotificationRequest; SignedFirmwareStatusNotificationConfirmation confirm = new(); if (_request.status != Packet.Messages.SubTypes.FirmwareStatusEnumType.Idle) { using (var db = await maindbContextFactory.CreateDbContextAsync()) { var item = await db.MachineOperateRecord.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.Action == "SignedUpdateFirmware" && x.RequestType == 1) .OrderByDescending(x => x.CreatedOn).FirstOrDefaultAsync(); if (item != null) { item.EVSE_Status = (int)_request.status; item.FinishedOn = DateTime.UtcNow; } await db.SaveChangesAsync(); } } result.Message = confirm; result.Success = true; return result; } default: { logger.LogWarning(string.Format("Not Implement {0} Logic(ExecuteCoreRequest)", request.GetType().ToString().Replace("OCPPPackage.Messages.Core.", ""))); } break; } } catch (Exception ex) { logger.LogCritical("chargeBoxId:{0} {1}", session.ChargeBoxId, action); logger.LogCritical("Data {0}", request.ToString()); logger.LogCritical("Error {0}", ex.ToString()); result.Exception = ex; } return result; } private bool CheckCsr(string chargeBoxId, string csrString) { string subject = certService.GetCertificateRequestSubject(csrString); logger.LogInformation("{chargeBoxId} send scr {subject}", chargeBoxId, subject); if (subject == null) { return false; } Dictionary csrInfo = certService.SubjectToDictionary(subject); if (csrInfo == null || !csrInfo.ContainsKey("CN") || csrInfo["CN"] != chargeBoxId) { return false; } return true; } internal async Task ExecuteSecurityConfirm(Actions action, WsClientData session, IConfirmation confirm, string requestId) { MessageResult result = new MessageResult() { Success = false }; switch (action) { case Actions.ExtendedTriggerMessage: { ExtendedTriggerMessageConfirmation _confirm = confirm as ExtendedTriggerMessageConfirmation; //ExtendedTriggerMessageRequest _request = _confirm.GetRequest() as ExtendedTriggerMessageRequest; using (var db = await maindbContextFactory.CreateDbContextAsync()) { var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync(); if (operation != null) { operation.FinishedOn = DateTime.UtcNow; operation.Status = 1;//電樁有回覆 operation.EVSE_Status = (int)_confirm.status;//OK operation.EVSE_Value = _confirm.status.ToString(); await db.SaveChangesAsync(); } } } break; case Actions.CertificateSigned: { CertificateSignedConfirmation _confirm = confirm as CertificateSignedConfirmation; using (var db = await maindbContextFactory.CreateDbContextAsync()) { var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync(); if (operation != null) { operation.FinishedOn = DateTime.UtcNow; operation.Status = 1;//電樁有回覆 operation.EVSE_Status = (int)_confirm.status;//OK operation.EVSE_Value = _confirm.status.ToString(); await db.SaveChangesAsync(); } } } break; case Actions.GetInstalledCertificateIds: { GetInstalledCertificateIdsConfirmation _confirm = confirm as GetInstalledCertificateIdsConfirmation; using (var db = await maindbContextFactory.CreateDbContextAsync()) { var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync(); if (operation != null) { operation.FinishedOn = DateTime.UtcNow; operation.Status = 1;//電樁有回覆 operation.EVSE_Status = (int)_confirm.status;//OK operation.EVSE_Value = _confirm.status.ToString(); await db.SaveChangesAsync(); } } } break; case Actions.DeleteCertificate: { DeleteCertificateConfirmation _confirm = confirm as DeleteCertificateConfirmation; using (var db = await maindbContextFactory.CreateDbContextAsync()) { var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync(); if (operation != null) { operation.FinishedOn = DateTime.UtcNow; operation.Status = 1;//電樁有回覆 operation.EVSE_Status = (int)_confirm.status;//OK operation.EVSE_Value = _confirm.status.ToString(); await db.SaveChangesAsync(); } } } break; case Actions.InstallCertificate: { InstallCertificateConfirmation _confirm = confirm as InstallCertificateConfirmation; using (var db = await maindbContextFactory.CreateDbContextAsync()) { var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync(); if (operation != null) { operation.FinishedOn = DateTime.UtcNow; operation.Status = 1;//電樁有回覆 operation.EVSE_Status = (int)_confirm.status;//OK operation.EVSE_Value = _confirm.status.ToString(); await db.SaveChangesAsync(); } } } break; case Actions.GetLog: { GetLogConfirmation _confirm = confirm as GetLogConfirmation; using (var db = await maindbContextFactory.CreateDbContextAsync()) { var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync(); if (operation != null) { operation.FinishedOn = DateTime.UtcNow; operation.Status = 1;//電樁有回覆 operation.EVSE_Status = (int)_confirm.status;//OK operation.EVSE_Value = _confirm.status.ToString(); await db.SaveChangesAsync(); } } } break; case Actions.SignedUpdateFirmware: { SignedUpdateFirmwareConfirmation _confirm = confirm as SignedUpdateFirmwareConfirmation; using (var db = await maindbContextFactory.CreateDbContextAsync()) { var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync(); if (operation != null) { operation.FinishedOn = DateTime.UtcNow; operation.Status = 1;//電樁有回覆 operation.EVSE_Status = (int)_confirm.status;//OK operation.EVSE_Value = _confirm.status.ToString(); await db.SaveChangesAsync(); } } } break; default: { logger.LogWarning(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.RemoteTrigger.", ""))); } break; } return result; } internal MessageResult ReceivedSecurityError(Actions action, string errorMsg, ClientData session, string requestId) { MessageResult result = new MessageResult() { Success = true }; switch (action) { default: { logger.LogWarning(string.Format("Not Implement {0} Logic", action)); } break; } return result; } } }