feat: Complete Phase 2 .NET implementation - Session & Service Management
- Add comprehensive XML parsing analysis methods for all 8 Phase 2 messages - ParseSessionSetupReqAnalysis/ParseSessionSetupResAnalysis: Session initialization - ParseServiceDiscoveryReqAnalysis/ParseServiceDiscoveryResAnalysis: Service discovery - ParseAuthorizationReqAnalysis/ParseAuthorizationResAnalysis: Authentication - ParseChargeParameterDiscoveryReqAnalysis/ParseChargeParameterDiscoveryResAnalysis: Parameter exchange - Add GetUnitString helper for physical value unit conversion - Include emoji indicators for better readability and debugging - All Phase 2 messages now fully implemented across C, VC2022, and .NET platforms 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -106,6 +106,71 @@ namespace V2GDecoderNet
|
||||
analysis.Append(ParseCurrentDemandReqAnalysis(currentDemandReq, ns3, ns4));
|
||||
}
|
||||
|
||||
// Phase 2: Session & Service Management Messages
|
||||
var sessionSetupReq = body.Element(ns3 + "SessionSetupReq");
|
||||
if (sessionSetupReq != null)
|
||||
{
|
||||
analysis.AppendLine("Message Type: SessionSetupReq");
|
||||
analysis.AppendLine();
|
||||
analysis.Append(ParseSessionSetupReqAnalysis(sessionSetupReq, ns3, ns4));
|
||||
}
|
||||
|
||||
var sessionSetupRes = body.Element(ns3 + "SessionSetupRes");
|
||||
if (sessionSetupRes != null)
|
||||
{
|
||||
analysis.AppendLine("Message Type: SessionSetupRes");
|
||||
analysis.AppendLine();
|
||||
analysis.Append(ParseSessionSetupResAnalysis(sessionSetupRes, ns3, ns4));
|
||||
}
|
||||
|
||||
var serviceDiscoveryReq = body.Element(ns3 + "ServiceDiscoveryReq");
|
||||
if (serviceDiscoveryReq != null)
|
||||
{
|
||||
analysis.AppendLine("Message Type: ServiceDiscoveryReq");
|
||||
analysis.AppendLine();
|
||||
analysis.Append(ParseServiceDiscoveryReqAnalysis(serviceDiscoveryReq, ns3, ns4));
|
||||
}
|
||||
|
||||
var serviceDiscoveryRes = body.Element(ns3 + "ServiceDiscoveryRes");
|
||||
if (serviceDiscoveryRes != null)
|
||||
{
|
||||
analysis.AppendLine("Message Type: ServiceDiscoveryRes");
|
||||
analysis.AppendLine();
|
||||
analysis.Append(ParseServiceDiscoveryResAnalysis(serviceDiscoveryRes, ns3, ns4));
|
||||
}
|
||||
|
||||
var authorizationReq = body.Element(ns3 + "AuthorizationReq");
|
||||
if (authorizationReq != null)
|
||||
{
|
||||
analysis.AppendLine("Message Type: AuthorizationReq");
|
||||
analysis.AppendLine();
|
||||
analysis.Append(ParseAuthorizationReqAnalysis(authorizationReq, ns3, ns4));
|
||||
}
|
||||
|
||||
var authorizationRes = body.Element(ns3 + "AuthorizationRes");
|
||||
if (authorizationRes != null)
|
||||
{
|
||||
analysis.AppendLine("Message Type: AuthorizationRes");
|
||||
analysis.AppendLine();
|
||||
analysis.Append(ParseAuthorizationResAnalysis(authorizationRes, ns3, ns4));
|
||||
}
|
||||
|
||||
var chargeParameterDiscoveryReq = body.Element(ns3 + "ChargeParameterDiscoveryReq");
|
||||
if (chargeParameterDiscoveryReq != null)
|
||||
{
|
||||
analysis.AppendLine("Message Type: ChargeParameterDiscoveryReq");
|
||||
analysis.AppendLine();
|
||||
analysis.Append(ParseChargeParameterDiscoveryReqAnalysis(chargeParameterDiscoveryReq, ns3, ns4));
|
||||
}
|
||||
|
||||
var chargeParameterDiscoveryRes = body.Element(ns3 + "ChargeParameterDiscoveryRes");
|
||||
if (chargeParameterDiscoveryRes != null)
|
||||
{
|
||||
analysis.AppendLine("Message Type: ChargeParameterDiscoveryRes");
|
||||
analysis.AppendLine();
|
||||
analysis.Append(ParseChargeParameterDiscoveryResAnalysis(chargeParameterDiscoveryRes, ns3, ns4));
|
||||
}
|
||||
|
||||
// Add other message types as needed
|
||||
}
|
||||
|
||||
@@ -766,5 +831,495 @@ namespace V2GDecoderNet
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static string ParseSessionSetupReqAnalysis(XElement sessionSetupReq, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var analysis = new StringBuilder();
|
||||
analysis.AppendLine("📋 Session Setup Request Analysis:");
|
||||
analysis.AppendLine(" Purpose: Initialize charging session with EVSE");
|
||||
analysis.AppendLine();
|
||||
|
||||
var evccId = sessionSetupReq.Element(ns3 + "EVCCID");
|
||||
if (evccId != null)
|
||||
{
|
||||
analysis.AppendLine($" 🔑 EV Controller ID: {evccId.Value}");
|
||||
analysis.AppendLine($" Length: {evccId.Value.Length} bytes");
|
||||
}
|
||||
|
||||
analysis.AppendLine(" 📊 Session Initialization Process");
|
||||
analysis.AppendLine(" ✅ Request sent to establish charging session");
|
||||
|
||||
return analysis.ToString();
|
||||
}
|
||||
|
||||
private static string ParseSessionSetupResAnalysis(XElement sessionSetupRes, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var analysis = new StringBuilder();
|
||||
analysis.AppendLine("📋 Session Setup Response Analysis:");
|
||||
analysis.AppendLine(" Purpose: Confirm session establishment");
|
||||
analysis.AppendLine();
|
||||
|
||||
var responseCode = sessionSetupRes.Element(ns3 + "ResponseCode");
|
||||
if (responseCode != null)
|
||||
{
|
||||
analysis.AppendLine($" 📊 Response Code: {responseCode.Value}");
|
||||
analysis.AppendLine($" Status: {(responseCode.Value == "OK" ? "✅ Success" : "❌ Failed")}");
|
||||
}
|
||||
|
||||
var evseId = sessionSetupRes.Element(ns3 + "EVSEID");
|
||||
if (evseId != null)
|
||||
{
|
||||
analysis.AppendLine($" 🏭 EVSE ID: {evseId.Value}");
|
||||
}
|
||||
|
||||
var evseTimeStamp = sessionSetupRes.Element(ns3 + "EVSETimeStamp");
|
||||
if (evseTimeStamp != null)
|
||||
{
|
||||
analysis.AppendLine($" ⏰ EVSE Timestamp: {evseTimeStamp.Value}");
|
||||
}
|
||||
|
||||
analysis.AppendLine(" 🔄 Session established successfully");
|
||||
|
||||
return analysis.ToString();
|
||||
}
|
||||
|
||||
private static string ParseServiceDiscoveryReqAnalysis(XElement serviceDiscoveryReq, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var analysis = new StringBuilder();
|
||||
analysis.AppendLine("🔍 Service Discovery Request Analysis:");
|
||||
analysis.AppendLine(" Purpose: Discover available charging services");
|
||||
analysis.AppendLine();
|
||||
|
||||
var serviceScope = serviceDiscoveryReq.Element(ns3 + "ServiceScope");
|
||||
if (serviceScope != null)
|
||||
{
|
||||
analysis.AppendLine($" 🎯 Service Scope: {serviceScope.Value}");
|
||||
}
|
||||
|
||||
var serviceCategory = serviceDiscoveryReq.Element(ns3 + "ServiceCategory");
|
||||
if (serviceCategory != null)
|
||||
{
|
||||
analysis.AppendLine($" 📂 Service Category: {serviceCategory.Value}");
|
||||
}
|
||||
|
||||
analysis.AppendLine(" 🔍 Requesting available services from EVSE");
|
||||
analysis.AppendLine(" 📋 Preparing for service selection phase");
|
||||
|
||||
return analysis.ToString();
|
||||
}
|
||||
|
||||
private static string ParseServiceDiscoveryResAnalysis(XElement serviceDiscoveryRes, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var analysis = new StringBuilder();
|
||||
analysis.AppendLine("🔍 Service Discovery Response Analysis:");
|
||||
analysis.AppendLine(" Purpose: Provide available charging services");
|
||||
analysis.AppendLine();
|
||||
|
||||
var responseCode = serviceDiscoveryRes.Element(ns3 + "ResponseCode");
|
||||
if (responseCode != null)
|
||||
{
|
||||
analysis.AppendLine($" 📊 Response Code: {responseCode.Value}");
|
||||
analysis.AppendLine($" Status: {(responseCode.Value == "OK" ? "✅ Success" : "❌ Failed")}");
|
||||
}
|
||||
|
||||
var paymentOptionList = serviceDiscoveryRes.Element(ns3 + "PaymentOptionList");
|
||||
if (paymentOptionList != null)
|
||||
{
|
||||
analysis.AppendLine(" 💳 Available Payment Options:");
|
||||
var paymentOptions = paymentOptionList.Elements(ns3 + "PaymentOption");
|
||||
foreach (var option in paymentOptions)
|
||||
{
|
||||
analysis.AppendLine($" • {option.Value}");
|
||||
}
|
||||
}
|
||||
|
||||
var chargeService = serviceDiscoveryRes.Element(ns3 + "ChargeService");
|
||||
if (chargeService != null)
|
||||
{
|
||||
analysis.AppendLine(" ⚡ Charging Service Available:");
|
||||
|
||||
var serviceId = chargeService.Element(ns3 + "ServiceID");
|
||||
if (serviceId != null)
|
||||
{
|
||||
analysis.AppendLine($" 🆔 Service ID: {serviceId.Value}");
|
||||
}
|
||||
|
||||
var serviceCategory = chargeService.Element(ns3 + "ServiceCategory");
|
||||
if (serviceCategory != null)
|
||||
{
|
||||
analysis.AppendLine($" 📂 Category: {serviceCategory.Value}");
|
||||
}
|
||||
|
||||
var freeService = chargeService.Element(ns3 + "FreeService");
|
||||
if (freeService != null)
|
||||
{
|
||||
analysis.AppendLine($" 💰 Free Service: {freeService.Value}");
|
||||
}
|
||||
}
|
||||
|
||||
var serviceList = serviceDiscoveryRes.Element(ns3 + "ServiceList");
|
||||
if (serviceList != null)
|
||||
{
|
||||
analysis.AppendLine(" 📋 Additional Services:");
|
||||
var services = serviceList.Elements(ns3 + "Service");
|
||||
int serviceCount = 0;
|
||||
foreach (var service in services)
|
||||
{
|
||||
serviceCount++;
|
||||
var serviceId = service.Element(ns3 + "ServiceID");
|
||||
var serviceName = service.Element(ns3 + "ServiceName");
|
||||
analysis.AppendLine($" {serviceCount}. ID: {serviceId?.Value}, Name: {serviceName?.Value}");
|
||||
}
|
||||
}
|
||||
|
||||
return analysis.ToString();
|
||||
}
|
||||
|
||||
private static string ParseAuthorizationReqAnalysis(XElement authorizationReq, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var analysis = new StringBuilder();
|
||||
analysis.AppendLine("🔐 Authorization Request Analysis:");
|
||||
analysis.AppendLine(" Purpose: Authenticate and authorize charging");
|
||||
analysis.AppendLine();
|
||||
|
||||
var idTokenInfo = authorizationReq.Element(ns3 + "Id");
|
||||
if (idTokenInfo != null)
|
||||
{
|
||||
analysis.AppendLine($" 🎫 ID Token: {idTokenInfo.Value}");
|
||||
}
|
||||
|
||||
var genChallenge = authorizationReq.Element(ns3 + "GenChallenge");
|
||||
if (genChallenge != null)
|
||||
{
|
||||
analysis.AppendLine($" 🔑 Generated Challenge: {genChallenge.Value}");
|
||||
analysis.AppendLine($" Length: {genChallenge.Value.Length} bytes");
|
||||
}
|
||||
|
||||
analysis.AppendLine(" 🔒 Requesting authorization for charging session");
|
||||
analysis.AppendLine(" 🛡️ Security challenge-response mechanism active");
|
||||
|
||||
return analysis.ToString();
|
||||
}
|
||||
|
||||
private static string ParseAuthorizationResAnalysis(XElement authorizationRes, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var analysis = new StringBuilder();
|
||||
analysis.AppendLine("🔐 Authorization Response Analysis:");
|
||||
analysis.AppendLine(" Purpose: Confirm authorization status");
|
||||
analysis.AppendLine();
|
||||
|
||||
var responseCode = authorizationRes.Element(ns3 + "ResponseCode");
|
||||
if (responseCode != null)
|
||||
{
|
||||
analysis.AppendLine($" 📊 Response Code: {responseCode.Value}");
|
||||
analysis.AppendLine($" Authorization: {(responseCode.Value == "OK" ? "✅ Granted" : "❌ Denied")}");
|
||||
}
|
||||
|
||||
var evseProcesing = authorizationRes.Element(ns3 + "EVSEProcessing");
|
||||
if (evseProcesing != null)
|
||||
{
|
||||
analysis.AppendLine($" ⚙️ EVSE Processing: {evseProcesing.Value}");
|
||||
string processingStatus = evseProcesing.Value switch
|
||||
{
|
||||
"Finished" => "✅ Complete",
|
||||
"Ongoing" => "🔄 In Progress",
|
||||
_ => "⚠️ Unknown"
|
||||
};
|
||||
analysis.AppendLine($" Status: {processingStatus}");
|
||||
}
|
||||
|
||||
analysis.AppendLine(" 🔓 Authorization process completed");
|
||||
|
||||
return analysis.ToString();
|
||||
}
|
||||
|
||||
private static string ParseChargeParameterDiscoveryReqAnalysis(XElement chargeParamReq, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var analysis = new StringBuilder();
|
||||
analysis.AppendLine("⚡ Charge Parameter Discovery Request Analysis:");
|
||||
analysis.AppendLine(" Purpose: Exchange charging parameters and capabilities");
|
||||
analysis.AppendLine();
|
||||
|
||||
var maxEntriesSaScheduleTuple = chargeParamReq.Element(ns3 + "MaxEntriesSAScheduleTuple");
|
||||
if (maxEntriesSaScheduleTuple != null)
|
||||
{
|
||||
analysis.AppendLine($" 📊 Max SA Schedule Entries: {maxEntriesSaScheduleTuple.Value}");
|
||||
}
|
||||
|
||||
var requestedEnergyTransferMode = chargeParamReq.Element(ns3 + "RequestedEnergyTransferMode");
|
||||
if (requestedEnergyTransferMode != null)
|
||||
{
|
||||
analysis.AppendLine($" 🔌 Energy Transfer Mode: {requestedEnergyTransferMode.Value}");
|
||||
}
|
||||
|
||||
var dcEvChargeParameter = chargeParamReq.Element(ns3 + "DC_EVChargeParameter");
|
||||
if (dcEvChargeParameter != null)
|
||||
{
|
||||
analysis.AppendLine(" 🔋 DC EV Charge Parameters:");
|
||||
|
||||
var dcEvStatus = dcEvChargeParameter.Element(ns4 + "DC_EVStatus");
|
||||
if (dcEvStatus != null)
|
||||
{
|
||||
var evReady = dcEvStatus.Element(ns4 + "EVReady");
|
||||
var evErrorCode = dcEvStatus.Element(ns4 + "EVErrorCode");
|
||||
var evRessSoc = dcEvStatus.Element(ns4 + "EVRESSSOC");
|
||||
|
||||
if (evReady != null)
|
||||
analysis.AppendLine($" 🚗 EV Ready: {evReady.Value}");
|
||||
if (evErrorCode != null)
|
||||
analysis.AppendLine($" ❌ Error Code: {evErrorCode.Value}");
|
||||
if (evRessSoc != null)
|
||||
analysis.AppendLine($" 🔋 Battery SoC: {evRessSoc.Value}%");
|
||||
}
|
||||
|
||||
var evMaxCurrent = dcEvChargeParameter.Element(ns4 + "EVMaximumCurrentLimit");
|
||||
if (evMaxCurrent != null)
|
||||
{
|
||||
var value = evMaxCurrent.Element(ns4 + "Value");
|
||||
var unit = evMaxCurrent.Element(ns4 + "Unit");
|
||||
var multiplier = evMaxCurrent.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" ⚡ Max Current: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evMaxVoltage = dcEvChargeParameter.Element(ns4 + "EVMaximumVoltageLimit");
|
||||
if (evMaxVoltage != null)
|
||||
{
|
||||
var value = evMaxVoltage.Element(ns4 + "Value");
|
||||
var unit = evMaxVoltage.Element(ns4 + "Unit");
|
||||
var multiplier = evMaxVoltage.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" 🔌 Max Voltage: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evMaxPower = dcEvChargeParameter.Element(ns4 + "EVMaximumPowerLimit");
|
||||
if (evMaxPower != null)
|
||||
{
|
||||
var value = evMaxPower.Element(ns4 + "Value");
|
||||
var unit = evMaxPower.Element(ns4 + "Unit");
|
||||
var multiplier = evMaxPower.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" ⚡ Max Power: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evEnergyCapacity = dcEvChargeParameter.Element(ns4 + "EVEnergyCapacity");
|
||||
if (evEnergyCapacity != null)
|
||||
{
|
||||
var value = evEnergyCapacity.Element(ns4 + "Value");
|
||||
var unit = evEnergyCapacity.Element(ns4 + "Unit");
|
||||
var multiplier = evEnergyCapacity.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" 🔋 Energy Capacity: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evEnergyRequest = dcEvChargeParameter.Element(ns4 + "EVEnergyRequest");
|
||||
if (evEnergyRequest != null)
|
||||
{
|
||||
var value = evEnergyRequest.Element(ns4 + "Value");
|
||||
var unit = evEnergyRequest.Element(ns4 + "Unit");
|
||||
var multiplier = evEnergyRequest.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" 🎯 Energy Request: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var fullSoc = dcEvChargeParameter.Element(ns4 + "FullSOC");
|
||||
if (fullSoc != null)
|
||||
{
|
||||
analysis.AppendLine($" 🔋 Full SoC: {fullSoc.Value}%");
|
||||
}
|
||||
|
||||
var bulkSoc = dcEvChargeParameter.Element(ns4 + "BulkSOC");
|
||||
if (bulkSoc != null)
|
||||
{
|
||||
analysis.AppendLine($" 🔋 Bulk SoC: {bulkSoc.Value}%");
|
||||
}
|
||||
}
|
||||
|
||||
analysis.AppendLine(" 📋 Requesting EVSE charging parameters");
|
||||
|
||||
return analysis.ToString();
|
||||
}
|
||||
|
||||
private static string ParseChargeParameterDiscoveryResAnalysis(XElement chargeParamRes, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var analysis = new StringBuilder();
|
||||
analysis.AppendLine("⚡ Charge Parameter Discovery Response Analysis:");
|
||||
analysis.AppendLine(" Purpose: Provide EVSE charging capabilities and schedules");
|
||||
analysis.AppendLine();
|
||||
|
||||
var responseCode = chargeParamRes.Element(ns3 + "ResponseCode");
|
||||
if (responseCode != null)
|
||||
{
|
||||
analysis.AppendLine($" 📊 Response Code: {responseCode.Value}");
|
||||
analysis.AppendLine($" Status: {(responseCode.Value == "OK" ? "✅ Success" : "❌ Failed")}");
|
||||
}
|
||||
|
||||
var evseProcesing = chargeParamRes.Element(ns3 + "EVSEProcessing");
|
||||
if (evseProcesing != null)
|
||||
{
|
||||
analysis.AppendLine($" ⚙️ EVSE Processing: {evseProcesing.Value}");
|
||||
}
|
||||
|
||||
var saScheduleList = chargeParamRes.Element(ns3 + "SAScheduleList");
|
||||
if (saScheduleList != null)
|
||||
{
|
||||
analysis.AppendLine(" 📅 SA Schedule List:");
|
||||
var schedules = saScheduleList.Elements(ns3 + "SAScheduleTuple");
|
||||
int scheduleCount = 0;
|
||||
foreach (var schedule in schedules)
|
||||
{
|
||||
scheduleCount++;
|
||||
analysis.AppendLine($" 📅 Schedule {scheduleCount}:");
|
||||
|
||||
var saScheduleTupleId = schedule.Element(ns4 + "SAScheduleTupleID");
|
||||
if (saScheduleTupleId != null)
|
||||
analysis.AppendLine($" 🆔 ID: {saScheduleTupleId.Value}");
|
||||
|
||||
var pMaxSchedule = schedule.Element(ns4 + "PMaxSchedule");
|
||||
if (pMaxSchedule != null)
|
||||
{
|
||||
analysis.AppendLine(" ⚡ Power Schedule:");
|
||||
var pMaxScheduleEntries = pMaxSchedule.Elements(ns4 + "PMaxScheduleEntry");
|
||||
foreach (var entry in pMaxScheduleEntries)
|
||||
{
|
||||
var relativeTimeInterval = entry.Element(ns4 + "RelativeTimeInterval");
|
||||
var pMax = entry.Element(ns4 + "PMax");
|
||||
if (relativeTimeInterval != null && pMax != null)
|
||||
{
|
||||
var start = relativeTimeInterval.Element(ns4 + "start");
|
||||
var duration = relativeTimeInterval.Element(ns4 + "duration");
|
||||
var pMaxValue = pMax.Element(ns4 + "Value");
|
||||
analysis.AppendLine($" ⏰ Start: {start?.Value}s, Duration: {duration?.Value}s, Power: {pMaxValue?.Value}W");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var salesTariff = schedule.Element(ns4 + "SalesTariff");
|
||||
if (salesTariff != null)
|
||||
{
|
||||
analysis.AppendLine(" 💰 Sales Tariff Available");
|
||||
var salesTariffId = salesTariff.Element(ns4 + "Id");
|
||||
if (salesTariffId != null)
|
||||
analysis.AppendLine($" 🆔 Tariff ID: {salesTariffId.Value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dcEvseChargeParameter = chargeParamRes.Element(ns3 + "DC_EVSEChargeParameter");
|
||||
if (dcEvseChargeParameter != null)
|
||||
{
|
||||
analysis.AppendLine(" 🏭 DC EVSE Charge Parameters:");
|
||||
|
||||
var dcEvseStatus = dcEvseChargeParameter.Element(ns4 + "DC_EVSEStatus");
|
||||
if (dcEvseStatus != null)
|
||||
{
|
||||
var notificationMaxDelay = dcEvseStatus.Element(ns4 + "NotificationMaxDelay");
|
||||
var evseNotification = dcEvseStatus.Element(ns4 + "EVSENotification");
|
||||
var evseIsolationStatus = dcEvseStatus.Element(ns4 + "EVSEIsolationStatus");
|
||||
|
||||
if (notificationMaxDelay != null)
|
||||
analysis.AppendLine($" ⏰ Max Notification Delay: {notificationMaxDelay.Value}s");
|
||||
if (evseNotification != null)
|
||||
analysis.AppendLine($" 📢 EVSE Notification: {evseNotification.Value}");
|
||||
if (evseIsolationStatus != null)
|
||||
analysis.AppendLine($" 🔌 Isolation Status: {evseIsolationStatus.Value}");
|
||||
}
|
||||
|
||||
var evseMaxCurrent = dcEvseChargeParameter.Element(ns4 + "EVSEMaximumCurrentLimit");
|
||||
if (evseMaxCurrent != null)
|
||||
{
|
||||
var value = evseMaxCurrent.Element(ns4 + "Value");
|
||||
var unit = evseMaxCurrent.Element(ns4 + "Unit");
|
||||
var multiplier = evseMaxCurrent.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" ⚡ EVSE Max Current: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evseMaxVoltage = dcEvseChargeParameter.Element(ns4 + "EVSEMaximumVoltageLimit");
|
||||
if (evseMaxVoltage != null)
|
||||
{
|
||||
var value = evseMaxVoltage.Element(ns4 + "Value");
|
||||
var unit = evseMaxVoltage.Element(ns4 + "Unit");
|
||||
var multiplier = evseMaxVoltage.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" 🔌 EVSE Max Voltage: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evseMaxPower = dcEvseChargeParameter.Element(ns4 + "EVSEMaximumPowerLimit");
|
||||
if (evseMaxPower != null)
|
||||
{
|
||||
var value = evseMaxPower.Element(ns4 + "Value");
|
||||
var unit = evseMaxPower.Element(ns4 + "Unit");
|
||||
var multiplier = evseMaxPower.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" ⚡ EVSE Max Power: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evseMinCurrent = dcEvseChargeParameter.Element(ns4 + "EVSEMinimumCurrentLimit");
|
||||
if (evseMinCurrent != null)
|
||||
{
|
||||
var value = evseMinCurrent.Element(ns4 + "Value");
|
||||
var unit = evseMinCurrent.Element(ns4 + "Unit");
|
||||
var multiplier = evseMinCurrent.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" ⚡ EVSE Min Current: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evseMinVoltage = dcEvseChargeParameter.Element(ns4 + "EVSEMinimumVoltageLimit");
|
||||
if (evseMinVoltage != null)
|
||||
{
|
||||
var value = evseMinVoltage.Element(ns4 + "Value");
|
||||
var unit = evseMinVoltage.Element(ns4 + "Unit");
|
||||
var multiplier = evseMinVoltage.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" 🔌 EVSE Min Voltage: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evseCurrentRegulationTolerance = dcEvseChargeParameter.Element(ns4 + "EVSECurrentRegulationTolerance");
|
||||
if (evseCurrentRegulationTolerance != null)
|
||||
{
|
||||
var value = evseCurrentRegulationTolerance.Element(ns4 + "Value");
|
||||
var unit = evseCurrentRegulationTolerance.Element(ns4 + "Unit");
|
||||
var multiplier = evseCurrentRegulationTolerance.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" 📊 Current Regulation Tolerance: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evsePeakCurrentRipple = dcEvseChargeParameter.Element(ns4 + "EVSEPeakCurrentRipple");
|
||||
if (evsePeakCurrentRipple != null)
|
||||
{
|
||||
var value = evsePeakCurrentRipple.Element(ns4 + "Value");
|
||||
var unit = evsePeakCurrentRipple.Element(ns4 + "Unit");
|
||||
var multiplier = evsePeakCurrentRipple.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" 🌊 Peak Current Ripple: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
|
||||
var evseEnergyToBeDelivered = dcEvseChargeParameter.Element(ns4 + "EVSEEnergyToBeDelivered");
|
||||
if (evseEnergyToBeDelivered != null)
|
||||
{
|
||||
var value = evseEnergyToBeDelivered.Element(ns4 + "Value");
|
||||
var unit = evseEnergyToBeDelivered.Element(ns4 + "Unit");
|
||||
var multiplier = evseEnergyToBeDelivered.Element(ns4 + "Multiplier");
|
||||
if (value != null)
|
||||
analysis.AppendLine($" 🎯 Energy To Deliver: {value.Value} {GetUnitString(unit?.Value)} (10^{multiplier?.Value ?? "0"})");
|
||||
}
|
||||
}
|
||||
|
||||
return analysis.ToString();
|
||||
}
|
||||
|
||||
private static string GetUnitString(string? unitValue)
|
||||
{
|
||||
return unitValue switch
|
||||
{
|
||||
"5" => "A", // Ampere
|
||||
"29" => "V", // Volt
|
||||
"38" => "W", // Watt
|
||||
"33" => "Wh", // Watt-hour
|
||||
"159" => "s", // Second
|
||||
_ => $"Unit({unitValue})"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user