feat: Add CurrentDemandRes encoding support to universal EXI codec
- Implemented complete CurrentDemandRes encoder following C grammar states 317-329 - Added EncodeCurrentDemandResType with proper response code, DC_EVSEStatus, voltage/current values - Added EncodeDC_EVSEStatusType for EVSE status with optional isolation status - Fixed missing EncodeString and EncodeMeterInfo methods for string and meter data encoding - Added EncodeInteger64 for 64-bit TMeter field support - Fixed type conversions (uint to int) for proper bit stream encoding - Verified encoding functionality with CurrentDemandRes test XML - Encoder now supports both CurrentDemandReq and CurrentDemandRes as minimum requirement - Structured for expansion to support all ISO 15118 message types (universal codec) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -446,7 +446,16 @@ namespace V2GDecoderNet
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsupported message type for encoding - only CurrentDemandReq supported");
|
||||
var currentDemandRes = bodyElement.Element(ns3 + "CurrentDemandRes");
|
||||
if (currentDemandRes != null)
|
||||
{
|
||||
v2gMessage.Body.CurrentDemandRes = ParseCurrentDemandResXml(currentDemandRes, ns3, ns4);
|
||||
v2gMessage.Body.CurrentDemandRes_isUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsupported message type for encoding - supported: CurrentDemandReq, CurrentDemandRes");
|
||||
}
|
||||
}
|
||||
|
||||
// Encode to EXI
|
||||
@@ -546,6 +555,130 @@ namespace V2GDecoderNet
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
private static CurrentDemandResType ParseCurrentDemandResXml(XElement resElement, XNamespace ns3, XNamespace ns4)
|
||||
{
|
||||
var res = new CurrentDemandResType();
|
||||
|
||||
// Parse ResponseCode
|
||||
var responseCode = resElement.Element(ns3 + "ResponseCode");
|
||||
if (responseCode != null)
|
||||
{
|
||||
res.ResponseCode = (ResponseCodeType)Enum.Parse(typeof(ResponseCodeType), responseCode.Value);
|
||||
}
|
||||
|
||||
// Parse DC_EVSEStatus
|
||||
var dcEvseStatus = resElement.Element(ns3 + "DC_EVSEStatus");
|
||||
if (dcEvseStatus != null)
|
||||
{
|
||||
res.DC_EVSEStatus = new DC_EVSEStatusType();
|
||||
|
||||
var notificationMaxDelay = dcEvseStatus.Element(ns4 + "NotificationMaxDelay");
|
||||
if (notificationMaxDelay != null)
|
||||
res.DC_EVSEStatus.NotificationMaxDelay = ushort.Parse(notificationMaxDelay.Value);
|
||||
|
||||
var evseNotification = dcEvseStatus.Element(ns4 + "EVSENotification");
|
||||
if (evseNotification != null)
|
||||
res.DC_EVSEStatus.EVSENotification = (EVSENotificationType)int.Parse(evseNotification.Value);
|
||||
|
||||
var evseIsolationStatus = dcEvseStatus.Element(ns4 + "EVSEIsolationStatus");
|
||||
if (evseIsolationStatus != null)
|
||||
{
|
||||
res.DC_EVSEStatus.EVSEIsolationStatus = (IsolationLevelType)int.Parse(evseIsolationStatus.Value);
|
||||
res.DC_EVSEStatus.EVSEIsolationStatus_isUsed = true;
|
||||
}
|
||||
|
||||
var evseStatusCode = dcEvseStatus.Element(ns4 + "EVSEStatusCode");
|
||||
if (evseStatusCode != null)
|
||||
res.DC_EVSEStatus.EVSEStatusCode = (DC_EVSEStatusCodeType)int.Parse(evseStatusCode.Value);
|
||||
}
|
||||
|
||||
// Parse EVSEPresentVoltage
|
||||
var evsePresentVoltage = resElement.Element(ns3 + "EVSEPresentVoltage");
|
||||
if (evsePresentVoltage != null)
|
||||
{
|
||||
res.EVSEPresentVoltage = ParsePhysicalValueXml(evsePresentVoltage, ns4);
|
||||
}
|
||||
|
||||
// Parse EVSEPresentCurrent
|
||||
var evsePresentCurrent = resElement.Element(ns3 + "EVSEPresentCurrent");
|
||||
if (evsePresentCurrent != null)
|
||||
{
|
||||
res.EVSEPresentCurrent = ParsePhysicalValueXml(evsePresentCurrent, ns4);
|
||||
}
|
||||
|
||||
// Parse boolean flags
|
||||
var evseCurrentLimitAchieved = resElement.Element(ns3 + "EVSECurrentLimitAchieved");
|
||||
if (evseCurrentLimitAchieved != null)
|
||||
res.EVSECurrentLimitAchieved = bool.Parse(evseCurrentLimitAchieved.Value);
|
||||
|
||||
var evseVoltageLimitAchieved = resElement.Element(ns3 + "EVSEVoltageLimitAchieved");
|
||||
if (evseVoltageLimitAchieved != null)
|
||||
res.EVSEVoltageLimitAchieved = bool.Parse(evseVoltageLimitAchieved.Value);
|
||||
|
||||
var evsePowerLimitAchieved = resElement.Element(ns3 + "EVSEPowerLimitAchieved");
|
||||
if (evsePowerLimitAchieved != null)
|
||||
res.EVSEPowerLimitAchieved = bool.Parse(evsePowerLimitAchieved.Value);
|
||||
|
||||
// Parse optional limits
|
||||
var evseMaximumVoltageLimit = resElement.Element(ns3 + "EVSEMaximumVoltageLimit");
|
||||
if (evseMaximumVoltageLimit != null)
|
||||
{
|
||||
res.EVSEMaximumVoltageLimit = ParsePhysicalValueXml(evseMaximumVoltageLimit, ns4);
|
||||
res.EVSEMaximumVoltageLimit_isUsed = true;
|
||||
}
|
||||
|
||||
var evseMaximumCurrentLimit = resElement.Element(ns3 + "EVSEMaximumCurrentLimit");
|
||||
if (evseMaximumCurrentLimit != null)
|
||||
{
|
||||
res.EVSEMaximumCurrentLimit = ParsePhysicalValueXml(evseMaximumCurrentLimit, ns4);
|
||||
res.EVSEMaximumCurrentLimit_isUsed = true;
|
||||
}
|
||||
|
||||
var evseMaximumPowerLimit = resElement.Element(ns3 + "EVSEMaximumPowerLimit");
|
||||
if (evseMaximumPowerLimit != null)
|
||||
{
|
||||
res.EVSEMaximumPowerLimit = ParsePhysicalValueXml(evseMaximumPowerLimit, ns4);
|
||||
res.EVSEMaximumPowerLimit_isUsed = true;
|
||||
}
|
||||
|
||||
// Parse EVSEID
|
||||
var evseid = resElement.Element(ns3 + "EVSEID");
|
||||
if (evseid != null)
|
||||
res.EVSEID = evseid.Value;
|
||||
|
||||
// Parse SAScheduleTupleID
|
||||
var saScheduleTupleId = resElement.Element(ns3 + "SAScheduleTupleID");
|
||||
if (saScheduleTupleId != null)
|
||||
res.SAScheduleTupleID = byte.Parse(saScheduleTupleId.Value);
|
||||
|
||||
// Parse MeterInfo (optional)
|
||||
var meterInfo = resElement.Element(ns3 + "MeterInfo");
|
||||
if (meterInfo != null)
|
||||
{
|
||||
res.MeterInfo = new MeterInfoType();
|
||||
|
||||
var meterID = meterInfo.Element(ns4 + "MeterID");
|
||||
if (meterID != null)
|
||||
res.MeterInfo.MeterID = meterID.Value;
|
||||
|
||||
var meterReading = meterInfo.Element(ns4 + "MeterReading");
|
||||
if (meterReading != null)
|
||||
res.MeterInfo.MeterReading = ulong.Parse(meterReading.Value);
|
||||
|
||||
res.MeterInfo_isUsed = true;
|
||||
}
|
||||
|
||||
// Parse ReceiptRequired (optional)
|
||||
var receiptRequired = resElement.Element(ns3 + "ReceiptRequired");
|
||||
if (receiptRequired != null)
|
||||
{
|
||||
res.ReceiptRequired = bool.Parse(receiptRequired.Value);
|
||||
res.ReceiptRequired_isUsed = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static PhysicalValueType ParsePhysicalValueXml(XElement element, XNamespace ns4)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user