Compare commits
4 Commits
fce7f41d00
...
64e445e21e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64e445e21e | ||
|
|
342ac4c8fb | ||
|
|
383706b236 | ||
|
|
bfd5fc6fe1 |
@@ -264,6 +264,10 @@ namespace V2GDecoderNet.EXI
|
||||
// VC2022 line 45: stream->buffer = (uint8_t)(stream->buffer << (nbits)) | (uint8_t)(val & (uint32_t)(0xff >> (uint32_t)(BITS_IN_BYTE - nbits)));
|
||||
uint mask = (uint)(0xFF >> (EXIConstantsExact.BITS_IN_BYTE - numBits));
|
||||
// Console.Error.WriteLine($"🔬 [writeBits] mask=0x{mask:X2}");
|
||||
if (_stream.Position >= 28 && _stream.Position <= 35 && _stream.Capacity == 1 && numBits == 1)
|
||||
{
|
||||
Console.Error.WriteLine($"🔍 [writeBits] LAST BIT: pos={_stream.Position}, cap={_stream.Capacity}, buf=0x{_stream.Buffer:X2}, val={val}, writing to LSB");
|
||||
}
|
||||
_stream.Buffer = (byte)((_stream.Buffer << numBits) | (val & mask));
|
||||
// Console.Error.WriteLine($"🔬 [writeBits] new buffer=0x{_stream.Buffer:X2}");
|
||||
|
||||
@@ -288,6 +292,11 @@ namespace V2GDecoderNet.EXI
|
||||
else
|
||||
{
|
||||
// VC2022 line 67-68: stream->buffer = (uint8_t)(stream->buffer << stream->capacity) | ( (uint8_t)(val >> (nbits - stream->capacity)) & (uint8_t)(0xff >> (BITS_IN_BYTE - stream->capacity)) );
|
||||
if (_stream.Position >= 28 && _stream.Position <= 35)
|
||||
{
|
||||
Console.Error.WriteLine($"🔍 [writeBits] BOUNDARY: pos={_stream.Position}, cap={_stream.Capacity}, buf=0x{_stream.Buffer:X2}, val={val}, nbits={numBits}");
|
||||
Console.Error.WriteLine($"🔍 [writeBits] shift_amount={numBits - _stream.Capacity}, val_shifted={(byte)(val >> (numBits - _stream.Capacity))}");
|
||||
}
|
||||
_stream.Buffer = (byte)((_stream.Buffer << _stream.Capacity) |
|
||||
(((byte)(val >> (numBits - _stream.Capacity))) & (byte)(0xFF >> (EXIConstantsExact.BITS_IN_BYTE - _stream.Capacity))));
|
||||
|
||||
@@ -297,6 +306,8 @@ namespace V2GDecoderNet.EXI
|
||||
// VC2022 line 75: stream->data[(*stream->pos)++] = stream->buffer;
|
||||
if (_stream.Position >= _stream.Size)
|
||||
throw new InvalidOperationException("Output buffer overflow");
|
||||
if (_stream.Position >= 28 && _stream.Position <= 35)
|
||||
Console.Error.WriteLine($"🔍 [writeBits] Writing byte 0x{_stream.Buffer:X2} to position {_stream.Position}");
|
||||
_stream.Data[_stream.Position++] = _stream.Buffer;
|
||||
|
||||
// VC2022 line 83: stream->buffer = 0;
|
||||
@@ -325,6 +336,8 @@ namespace V2GDecoderNet.EXI
|
||||
/// </summary>
|
||||
public void WriteBit(int bit)
|
||||
{
|
||||
if (Position >= 28 && Position <= 35)
|
||||
Console.Error.WriteLine($"🔍 [WriteBit] pos={Position}:{BitPosition}, bit={bit}");
|
||||
writeBits(1, bit);
|
||||
}
|
||||
|
||||
@@ -333,11 +346,11 @@ namespace V2GDecoderNet.EXI
|
||||
/// </summary>
|
||||
public void WriteBits(int numBits, int val)
|
||||
{
|
||||
// if (Position >= 28 && Position <= 35)
|
||||
// Console.Error.WriteLine($"🔍 [WriteBits] pos={Position}, writing {numBits} bits, val={val:X}");
|
||||
if (Position >= 28 && Position <= 45)
|
||||
Console.Error.WriteLine($"🔍 [WriteBits] pos={Position}, writing {numBits} bits, val={val:X}");
|
||||
writeBits(numBits, val);
|
||||
// if (Position >= 28 && Position <= 35)
|
||||
// Console.Error.WriteLine($"🔍 [WriteBits] pos after={Position}");
|
||||
if (Position >= 28 && Position <= 45)
|
||||
Console.Error.WriteLine($"🔍 [WriteBits] pos after={Position}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -348,7 +361,8 @@ namespace V2GDecoderNet.EXI
|
||||
{
|
||||
if (numBits > 0)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔬 [encodeNBit] Writing {numBits} bits, value {val}, pos_before={Position}, buf=0x{BufferState:X2}, cap={CapacityState}");
|
||||
if (Position >= 28 && Position <= 35)
|
||||
Console.Error.WriteLine($"🔍 [encodeNBit] pos={Position}:{BitPosition}, writing {numBits} bits, val={val}");
|
||||
writeBits(numBits, val);
|
||||
// Console.Error.WriteLine($"🔬 [encodeNBit] After write pos_after={Position}, buf=0x{BufferState:X2}, cap={CapacityState}");
|
||||
}
|
||||
@@ -357,6 +371,9 @@ namespace V2GDecoderNet.EXI
|
||||
/// <summary>
|
||||
/// Compatibility wrapper - keep C# naming for internal use
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Legacy C# style alias for backward compatibility
|
||||
/// </summary>
|
||||
public void WriteNBitUnsignedInteger(int numBits, int val) => encodeNBitUnsignedInteger(numBits, val);
|
||||
|
||||
/// <summary>
|
||||
@@ -554,9 +571,12 @@ namespace V2GDecoderNet.EXI
|
||||
/// </summary>
|
||||
public void WriteInteger16(short val)
|
||||
{
|
||||
Console.Error.WriteLine($"🔢 [WriteInteger16] Input: {val}");
|
||||
|
||||
// Write sign bit (1 bit)
|
||||
bool isNegative = val < 0;
|
||||
WriteBit(isNegative ? 1 : 0);
|
||||
Console.Error.WriteLine($"🔢 [WriteInteger16] Sign bit: {(isNegative ? 1 : 0)} (negative: {isNegative})");
|
||||
|
||||
// Calculate unsigned magnitude
|
||||
uint magnitude;
|
||||
@@ -571,6 +591,8 @@ namespace V2GDecoderNet.EXI
|
||||
magnitude = (uint)val;
|
||||
}
|
||||
|
||||
Console.Error.WriteLine($"🔢 [WriteInteger16] Magnitude: {magnitude}");
|
||||
|
||||
// Write unsigned magnitude using VC2022's encodeUnsignedInteger16
|
||||
encodeUnsignedInteger16((ushort)magnitude);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace V2GDecoderNet
|
||||
{
|
||||
@@ -20,6 +21,7 @@ namespace V2GDecoderNet
|
||||
private const ushort V2G_PAYLOAD_ISO2 = 0x8002; // ISO 15118-20 payload type
|
||||
private const ushort EXI_START_PATTERN = 0x8098; // EXI document start pattern
|
||||
|
||||
|
||||
static int Main(string[] args)
|
||||
{
|
||||
bool xmlMode = false;
|
||||
@@ -52,16 +54,17 @@ namespace V2GDecoderNet
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error.WriteLine($"Usage: {Environment.GetCommandLineArgs()[0]} [-debug] [-decode|-encode] input_file");
|
||||
Console.Error.WriteLine($" {Environment.GetCommandLineArgs()[0]} [-debug] -encode (read XML from stdin)");
|
||||
Console.Error.WriteLine($" {Environment.GetCommandLineArgs()[0]} [-debug] -decode (read hex string from stdin)");
|
||||
Console.Error.WriteLine("Usage: V2GDecoderNet [-decode|-encode] input_file");
|
||||
Console.Error.WriteLine(" V2GDecoderNet -encode (read XML from stdin)");
|
||||
Console.Error.WriteLine(" V2GDecoderNet -decode (read hex string from stdin)");
|
||||
Console.Error.WriteLine("Enhanced EXI viewer with XML conversion capabilities");
|
||||
Console.Error.WriteLine(" -debug Enable detailed bit-level encoding/decoding output");
|
||||
Console.Error.WriteLine(" -decode Convert EXI to Wireshark-style XML format");
|
||||
Console.Error.WriteLine(" -decode Read hex string from stdin (echo hex | app -decode)");
|
||||
Console.Error.WriteLine(" -decode Read hex string from stdin (echo hex | V2GDecoderNet -decode)");
|
||||
Console.Error.WriteLine(" -encode Convert XML to EXI format");
|
||||
Console.Error.WriteLine(" -encode Read XML from stdin (type file.xml | app -encode)");
|
||||
Console.Error.WriteLine(" -encode Read XML from stdin (type file.xml | V2GDecoderNet -encode)");
|
||||
Console.Error.WriteLine(" (default) Analyze EXI with detailed output");
|
||||
Console.Error.WriteLine("");
|
||||
Console.Error.WriteLine("Contact: tindevil82@gmail.com");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -105,12 +108,23 @@ namespace V2GDecoderNet
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Force binary output using stream approach
|
||||
// Check if output is redirected
|
||||
bool isRedirected = Console.IsOutputRedirected;
|
||||
|
||||
if (isRedirected)
|
||||
{
|
||||
// Binary output for redirection (file output)
|
||||
using (var stdout = Console.OpenStandardOutput())
|
||||
{
|
||||
stdout.Write(exiData, 0, exiData.Length);
|
||||
stdout.Flush();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hex string output for console display
|
||||
Console.Write(BitConverter.ToString(exiData).Replace("-", ""));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -158,14 +172,35 @@ namespace V2GDecoderNet
|
||||
}
|
||||
|
||||
// Decode EXI message
|
||||
var result = V2GMessageProcessor.DecodeExiMessage(exiBuffer);
|
||||
DecodeResult result;
|
||||
if (xmlMode)
|
||||
{
|
||||
// Suppress debug output for XML-only mode
|
||||
using (var sw = new StringWriter())
|
||||
{
|
||||
var originalOut = Console.Out;
|
||||
Console.SetOut(sw);
|
||||
try
|
||||
{
|
||||
result = V2GMessageProcessor.DecodeExiMessage(exiBuffer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.SetOut(originalOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = V2GMessageProcessor.DecodeExiMessage(exiBuffer);
|
||||
}
|
||||
|
||||
if (result.Success)
|
||||
{
|
||||
if (xmlMode)
|
||||
{
|
||||
// XML decode mode - output Wireshark-style XML
|
||||
Console.WriteLine(result.XmlOutput);
|
||||
// XML decode mode - output clean XML only
|
||||
Console.Write(result.XmlOutput);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -315,12 +350,23 @@ namespace V2GDecoderNet
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Output binary data to stdout
|
||||
// Check if output is redirected
|
||||
bool isRedirected = Console.IsOutputRedirected;
|
||||
|
||||
if (isRedirected)
|
||||
{
|
||||
// Binary output for redirection
|
||||
using (var stdout = Console.OpenStandardOutput())
|
||||
{
|
||||
stdout.Write(exiData, 0, exiData.Length);
|
||||
stdout.Flush();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hex string output for console display
|
||||
Console.Write(BitConverter.ToString(exiData).Replace("-", ""));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"profiles": {
|
||||
"V2GDecoderNet": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "-encode s:\\Source\\SYSDOC\\V2GDecoderC\\test5.xml"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ namespace V2GDecoderNet.V2G
|
||||
|
||||
// Step 2: Encode V2G_Message choice 76 in 7-bit encoding
|
||||
// matches: if(exiDoc->V2G_Message_isUsed == 1u) encodeNBitUnsignedInteger(stream, 7, 76);
|
||||
stream.WriteNBitUnsignedInteger(7, 76);
|
||||
stream.encodeNBitUnsignedInteger(7, 76);
|
||||
|
||||
// Step 3: Encode V2G_Message structure - Grammar states 256→257→3
|
||||
EncodeAnonType_V2G_Message(stream, message);
|
||||
@@ -229,21 +229,21 @@ namespace V2GDecoderNet.V2G
|
||||
{
|
||||
case 256: // Grammar 256: Header is mandatory
|
||||
// Console.Error.WriteLine($"🔍 [Grammar 256] Encoding Header, position: {stream.Position}");
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(Header)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(Header)
|
||||
EncodeMessageHeaderType(stream, message);
|
||||
grammarID = 257;
|
||||
break;
|
||||
|
||||
case 257: // Grammar 257: Body is mandatory
|
||||
// Console.Error.WriteLine($"🔍 [Grammar 257] Encoding Body, position: {stream.Position}");
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(Body)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(Body)
|
||||
EncodeBodyType(stream, message.Body);
|
||||
grammarID = 3;
|
||||
break;
|
||||
|
||||
case 3: // Grammar 3: END_ELEMENT
|
||||
// Console.Error.WriteLine($"🔍 [Grammar 3] END_ELEMENT, position: {stream.Position}");
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // END_ELEMENT
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // END_ELEMENT
|
||||
done = true;
|
||||
break;
|
||||
|
||||
@@ -265,10 +265,10 @@ namespace V2GDecoderNet.V2G
|
||||
// Console.Error.WriteLine($"🔍 [MessageHeader] Starting encoding, position: {stream.Position}");
|
||||
|
||||
// Grammar state 0: SessionID is mandatory
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(SessionID)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(SessionID)
|
||||
|
||||
// SessionID BINARY_HEX encoding - exact match to VC2022
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[BINARY_HEX]
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[BINARY_HEX]
|
||||
|
||||
// Convert SessionID hex string to bytes - exact match to VC2022 structure
|
||||
byte[] sessionIdBytes = ConvertHexStringToBytes(message.SessionID ?? "4142423030303831");
|
||||
@@ -284,10 +284,10 @@ namespace V2GDecoderNet.V2G
|
||||
}
|
||||
// Console.Error.WriteLine($"🔍 [SessionID] Bytes written, position: {stream.Position}");
|
||||
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
// Grammar state 1: Skip optional Notification, Signature → END_ELEMENT
|
||||
stream.WriteNBitUnsignedInteger(2, 2); // END_ELEMENT choice (choice 2 in 2-bit)
|
||||
stream.encodeNBitUnsignedInteger(2, 2); // END_ELEMENT choice (choice 2 in 2-bit)
|
||||
|
||||
// Console.Error.WriteLine($"🔍 [MessageHeader] Encoding completed, position: {stream.Position}");
|
||||
}
|
||||
@@ -304,13 +304,13 @@ namespace V2GDecoderNet.V2G
|
||||
if (body.CurrentDemandReq_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 [Body] Encoding CurrentDemandReq (choice 13)");
|
||||
stream.WriteNBitUnsignedInteger(6, 13); // CurrentDemandReq = choice 13
|
||||
stream.encodeNBitUnsignedInteger(6, 13); // CurrentDemandReq = choice 13
|
||||
EncodeCurrentDemandReqType(stream, body.CurrentDemandReq);
|
||||
}
|
||||
else if (body.CurrentDemandRes_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 [Body] Encoding CurrentDemandRes (choice 14)");
|
||||
stream.WriteNBitUnsignedInteger(6, 14); // CurrentDemandRes = choice 14
|
||||
stream.encodeNBitUnsignedInteger(6, 14); // CurrentDemandRes = choice 14
|
||||
EncodeCurrentDemandResType(stream, body.CurrentDemandRes);
|
||||
}
|
||||
else
|
||||
@@ -320,7 +320,7 @@ namespace V2GDecoderNet.V2G
|
||||
}
|
||||
|
||||
// Grammar state 3: END_ELEMENT
|
||||
stream.WriteNBitUnsignedInteger(1, 0);
|
||||
stream.encodeNBitUnsignedInteger(1, 0);
|
||||
|
||||
// Console.Error.WriteLine($"🔍 [Body] Encoding completed, position: {stream.Position}");
|
||||
}
|
||||
@@ -343,13 +343,13 @@ namespace V2GDecoderNet.V2G
|
||||
switch (grammarID)
|
||||
{
|
||||
case 273: // DC_EVStatus is mandatory
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(DC_EVStatus)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(DC_EVStatus)
|
||||
EncodeDC_EVStatusType(stream, req.DC_EVStatus);
|
||||
grammarID = 274;
|
||||
break;
|
||||
|
||||
case 274: // EVTargetCurrent is mandatory
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(EVTargetCurrent)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(EVTargetCurrent)
|
||||
EncodePhysicalValueType(stream, req.EVTargetCurrent);
|
||||
grammarID = 275;
|
||||
break;
|
||||
@@ -363,35 +363,35 @@ namespace V2GDecoderNet.V2G
|
||||
if (req.EVMaximumVoltageLimit_isUsed)
|
||||
{
|
||||
Console.Error.WriteLine($"🔍 Grammar 275: choice 0 (EVMaximumVoltageLimit), 3-bit=0");
|
||||
stream.WriteNBitUnsignedInteger(3, 0);
|
||||
stream.encodeNBitUnsignedInteger(3, 0);
|
||||
EncodePhysicalValueType(stream, req.EVMaximumVoltageLimit);
|
||||
grammarID = 276;
|
||||
}
|
||||
else if (req.EVMaximumCurrentLimit_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 Grammar 275: choice 1 (EVMaximumCurrentLimit), 3-bit=1");
|
||||
stream.WriteNBitUnsignedInteger(3, 1);
|
||||
stream.encodeNBitUnsignedInteger(3, 1);
|
||||
EncodePhysicalValueType(stream, req.EVMaximumCurrentLimit);
|
||||
grammarID = 277;
|
||||
}
|
||||
else if (req.EVMaximumPowerLimit_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 Grammar 275: choice 2 (EVMaximumPowerLimit), 3-bit=2");
|
||||
stream.WriteNBitUnsignedInteger(3, 2);
|
||||
stream.encodeNBitUnsignedInteger(3, 2);
|
||||
EncodePhysicalValueType(stream, req.EVMaximumPowerLimit);
|
||||
grammarID = 278;
|
||||
}
|
||||
else if (req.BulkChargingComplete_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 Grammar 275: choice 3 (BulkChargingComplete), 3-bit=3");
|
||||
stream.WriteNBitUnsignedInteger(3, 3);
|
||||
stream.encodeNBitUnsignedInteger(3, 3);
|
||||
EncodeBooleanElement(stream, req.BulkChargingComplete);
|
||||
grammarID = 279;
|
||||
}
|
||||
else // ChargingComplete is mandatory default (if( 1 == 1 ))
|
||||
{
|
||||
Console.Error.WriteLine($"🔍 Grammar 275: choice 4 (ChargingComplete), 3-bit=4");
|
||||
stream.WriteNBitUnsignedInteger(3, 4);
|
||||
stream.encodeNBitUnsignedInteger(3, 4);
|
||||
EncodeBooleanElement(stream, req.ChargingComplete);
|
||||
grammarID = 280;
|
||||
}
|
||||
@@ -405,28 +405,28 @@ namespace V2GDecoderNet.V2G
|
||||
if (req.EVMaximumCurrentLimit_isUsed)
|
||||
{
|
||||
Console.Error.WriteLine($"🔍 Grammar 276: choice 0 (EVMaximumCurrentLimit), 3-bit=0");
|
||||
stream.WriteNBitUnsignedInteger(3, 0);
|
||||
stream.encodeNBitUnsignedInteger(3, 0);
|
||||
EncodePhysicalValueType(stream, req.EVMaximumCurrentLimit);
|
||||
grammarID = 277;
|
||||
}
|
||||
else if (req.EVMaximumPowerLimit_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 Grammar 276: choice 1 (EVMaximumPowerLimit), 3-bit=1");
|
||||
stream.WriteNBitUnsignedInteger(3, 1);
|
||||
stream.encodeNBitUnsignedInteger(3, 1);
|
||||
EncodePhysicalValueType(stream, req.EVMaximumPowerLimit);
|
||||
grammarID = 278;
|
||||
}
|
||||
else if (req.BulkChargingComplete_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 Grammar 276: choice 2 (BulkChargingComplete), 3-bit=2");
|
||||
stream.WriteNBitUnsignedInteger(3, 2);
|
||||
stream.encodeNBitUnsignedInteger(3, 2);
|
||||
EncodeBooleanElement(stream, req.BulkChargingComplete);
|
||||
grammarID = 279;
|
||||
}
|
||||
else // ChargingComplete (if( 1 == 1 ))
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 Grammar 276: choice 3 (ChargingComplete), 3-bit=3");
|
||||
stream.WriteNBitUnsignedInteger(3, 3);
|
||||
stream.encodeNBitUnsignedInteger(3, 3);
|
||||
EncodeBooleanElement(stream, req.ChargingComplete);
|
||||
grammarID = 280;
|
||||
}
|
||||
@@ -439,21 +439,21 @@ namespace V2GDecoderNet.V2G
|
||||
if (req.EVMaximumPowerLimit_isUsed)
|
||||
{
|
||||
Console.Error.WriteLine($"🔍 Grammar 277: choice 0 (EVMaximumPowerLimit), 2-bit=0");
|
||||
stream.WriteNBitUnsignedInteger(2, 0);
|
||||
stream.encodeNBitUnsignedInteger(2, 0);
|
||||
EncodePhysicalValueType(stream, req.EVMaximumPowerLimit);
|
||||
grammarID = 278;
|
||||
}
|
||||
else if (req.BulkChargingComplete_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 Grammar 277: choice 1 (BulkChargingComplete), 2-bit=1");
|
||||
stream.WriteNBitUnsignedInteger(2, 1);
|
||||
stream.encodeNBitUnsignedInteger(2, 1);
|
||||
EncodeBooleanElement(stream, req.BulkChargingComplete);
|
||||
grammarID = 279;
|
||||
}
|
||||
else // ChargingComplete (if( 1 == 1 ))
|
||||
{
|
||||
// Console.Error.WriteLine($"🔍 Grammar 277: choice 2 (ChargingComplete), 2-bit=2");
|
||||
stream.WriteNBitUnsignedInteger(2, 2);
|
||||
stream.encodeNBitUnsignedInteger(2, 2);
|
||||
EncodeBooleanElement(stream, req.ChargingComplete);
|
||||
grammarID = 280;
|
||||
}
|
||||
@@ -464,85 +464,107 @@ namespace V2GDecoderNet.V2G
|
||||
|
||||
if (req.BulkChargingComplete_isUsed)
|
||||
{
|
||||
// Console.Error.WriteLine($"📍 Grammar 278: choice 0 (BulkChargingComplete), 2-bit=0");
|
||||
stream.WriteNBitUnsignedInteger(2, 0);
|
||||
Console.Error.WriteLine($"📍 Grammar 278: choice 0 (BulkChargingComplete), 2-bit=0");
|
||||
stream.encodeNBitUnsignedInteger(2, 0);
|
||||
EncodeBooleanElement(stream, req.BulkChargingComplete);
|
||||
grammarID = 279;
|
||||
}
|
||||
else // ChargingComplete (if( 1 == 1 ))
|
||||
{
|
||||
Console.Error.WriteLine($"📍 Grammar 278: choice 1 (ChargingComplete), 2-bit=1");
|
||||
stream.WriteNBitUnsignedInteger(2, 1);
|
||||
stream.encodeNBitUnsignedInteger(2, 1);
|
||||
EncodeBooleanElement(stream, req.ChargingComplete);
|
||||
grammarID = 280;
|
||||
}
|
||||
break;
|
||||
|
||||
case 279: // After BulkChargingComplete - skip to optional elements
|
||||
if (req.RemainingTimeToFullSoC_isUsed)
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(2, 0);
|
||||
EncodePhysicalValueType(stream, req.RemainingTimeToFullSoC);
|
||||
grammarID = 281;
|
||||
}
|
||||
else if (req.RemainingTimeToBulkSoC_isUsed)
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(2, 1);
|
||||
EncodePhysicalValueType(stream, req.RemainingTimeToBulkSoC);
|
||||
grammarID = 282;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(2, 2);
|
||||
EncodePhysicalValueType(stream, req.EVTargetVoltage); // Mandatory
|
||||
grammarID = 3; // END
|
||||
}
|
||||
case 279: // After BulkChargingComplete - VC2022: 1-bit choice for ChargingComplete
|
||||
Console.Error.WriteLine($"🔍 Grammar 279: ChargingComplete always required (1==1)");
|
||||
|
||||
// VC2022 Grammar 279: 1-bit choice, not 2-bit!
|
||||
Console.Error.WriteLine($"📍 Grammar 279: choice 0 (ChargingComplete={req.ChargingComplete}), 1-bit=0");
|
||||
stream.encodeNBitUnsignedInteger(1, 0);
|
||||
EncodeBooleanElement(stream, req.ChargingComplete);
|
||||
grammarID = 280;
|
||||
break;
|
||||
|
||||
case 280: // After ChargingComplete - 2-bit choice
|
||||
Console.Error.WriteLine($"🔍 Grammar 280: RemainingTimeToFullSoC_isUsed={req.RemainingTimeToFullSoC_isUsed}");
|
||||
Console.Error.WriteLine($"🔍 Grammar 280: RemainingTimeToBulkSoC_isUsed={req.RemainingTimeToBulkSoC_isUsed}");
|
||||
if (req.RemainingTimeToFullSoC_isUsed)
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(2, 0);
|
||||
stream.encodeNBitUnsignedInteger(2, 0);
|
||||
EncodePhysicalValueType(stream, req.RemainingTimeToFullSoC);
|
||||
grammarID = 281;
|
||||
}
|
||||
else if (req.RemainingTimeToBulkSoC_isUsed)
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(2, 1);
|
||||
stream.encodeNBitUnsignedInteger(2, 1);
|
||||
EncodePhysicalValueType(stream, req.RemainingTimeToBulkSoC);
|
||||
grammarID = 282;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(2, 2);
|
||||
EncodePhysicalValueType(stream, req.EVTargetVoltage); // Mandatory
|
||||
grammarID = 3; // END
|
||||
// Skip to Grammar 283 (EVTargetVoltage processing)
|
||||
stream.encodeNBitUnsignedInteger(2, 2);
|
||||
grammarID = 283;
|
||||
}
|
||||
break;
|
||||
|
||||
case 281: // After RemainingTimeToFullSoC - 2-bit choice
|
||||
Console.Error.WriteLine($"🔍 Grammar 281: RemainingTimeToBulkSoC_isUsed={req.RemainingTimeToBulkSoC_isUsed}");
|
||||
Console.Error.WriteLine($"🔍 Grammar 281: EVTargetVoltage != null = {req.EVTargetVoltage != null}");
|
||||
if (req.RemainingTimeToBulkSoC_isUsed)
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(2, 0);
|
||||
Console.Error.WriteLine("📍 Grammar 281: choice 0 (RemainingTimeToBulkSoC), 2-bit=0");
|
||||
stream.encodeNBitUnsignedInteger(2, 0);
|
||||
EncodePhysicalValueType(stream, req.RemainingTimeToBulkSoC);
|
||||
grammarID = 282;
|
||||
}
|
||||
else if (req.EVTargetVoltage != null) // EVTargetVoltage_isUsed equivalent
|
||||
{
|
||||
Console.Error.WriteLine("📍 Grammar 281: choice 1 (EVTargetVoltage), 2-bit=1");
|
||||
stream.encodeNBitUnsignedInteger(2, 1);
|
||||
EncodePhysicalValueType(stream, req.EVTargetVoltage);
|
||||
grammarID = 3; // END
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(2, 1);
|
||||
EncodePhysicalValueType(stream, req.EVTargetVoltage); // Mandatory
|
||||
Console.Error.WriteLine("📍 Grammar 281: choice 2 (END_ELEMENT), 2-bit=2");
|
||||
stream.encodeNBitUnsignedInteger(2, 2); // END_ELEMENT choice
|
||||
grammarID = 3; // END
|
||||
}
|
||||
break;
|
||||
|
||||
case 282: // After RemainingTimeToBulkSoC - 1-bit choice
|
||||
stream.WriteNBitUnsignedInteger(1, 0);
|
||||
EncodePhysicalValueType(stream, req.EVTargetVoltage); // Mandatory
|
||||
Console.Error.WriteLine($"🔍 Grammar 282: EVTargetVoltage != null = {req.EVTargetVoltage != null}");
|
||||
// Check EVTargetVoltage_isUsed flag like VC2022
|
||||
if (req.EVTargetVoltage != null) // EVTargetVoltage_isUsed equivalent
|
||||
{
|
||||
Console.Error.WriteLine("📍 Grammar 282: choice 0 (EVTargetVoltage), 1-bit=0");
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // choice 0
|
||||
EncodePhysicalValueType(stream, req.EVTargetVoltage);
|
||||
grammarID = 3; // END
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error.WriteLine("📍 Grammar 282: choice 1 (END_ELEMENT), 1-bit=1");
|
||||
stream.encodeNBitUnsignedInteger(1, 1); // choice 1 - END_ELEMENT
|
||||
grammarID = 3; // END
|
||||
}
|
||||
break;
|
||||
|
||||
case 283: // EVTargetVoltage processing
|
||||
// This grammar state handles EVTargetVoltage directly
|
||||
if (req.EVTargetVoltage != null) // EVTargetVoltage_isUsed equivalent
|
||||
{
|
||||
EncodePhysicalValueType(stream, req.EVTargetVoltage);
|
||||
}
|
||||
grammarID = 3; // END
|
||||
break;
|
||||
|
||||
case 3: // END_ELEMENT
|
||||
stream.WriteNBitUnsignedInteger(1, 0);
|
||||
stream.encodeNBitUnsignedInteger(1, 0);
|
||||
done = true;
|
||||
break;
|
||||
|
||||
@@ -563,13 +585,13 @@ namespace V2GDecoderNet.V2G
|
||||
// Console.Error.WriteLine($"🔍 [CurrentDemandRes] Starting encoding, position: {stream.Position}");
|
||||
|
||||
// Grammar 317: ResponseCode (mandatory)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(ResponseCode)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION]
|
||||
stream.WriteNBitUnsignedInteger(5, (int)res.ResponseCode); // 5-bit enumeration
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(ResponseCode)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION]
|
||||
stream.encodeNBitUnsignedInteger(5, (int)res.ResponseCode); // 5-bit enumeration
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
// Simple implementation - skip complex grammar for now
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // END_ELEMENT
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // END_ELEMENT
|
||||
|
||||
// Console.Error.WriteLine($"🔍 [CurrentDemandRes] Encoding completed, position: {stream.Position}");
|
||||
}
|
||||
@@ -583,25 +605,25 @@ namespace V2GDecoderNet.V2G
|
||||
// Console.Error.WriteLine($"🔍 [DC_EVStatus] Starting encoding, position: {stream.Position}");
|
||||
|
||||
// Grammar 314: EVReady (mandatory boolean)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(EVReady)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[BOOLEAN]
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(EVReady)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[BOOLEAN]
|
||||
stream.WriteBit(status.EVReady ? 1 : 0); // Boolean bit
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
// Grammar 315: EVErrorCode (mandatory enumeration)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(EVErrorCode)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION]
|
||||
stream.WriteNBitUnsignedInteger(4, status.EVErrorCode); // 4-bit enumeration
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(EVErrorCode)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION]
|
||||
stream.encodeNBitUnsignedInteger(4, status.EVErrorCode); // 4-bit enumeration
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
// Grammar 316: EVRESSSOC (mandatory 7-bit unsigned integer)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(EVRESSSOC)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[NBIT_UNSIGNED_INTEGER]
|
||||
stream.WriteNBitUnsignedInteger(7, status.EVRESSSOC); // 7-bit unsigned (0-100)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(EVRESSSOC)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[NBIT_UNSIGNED_INTEGER]
|
||||
stream.encodeNBitUnsignedInteger(7, status.EVRESSSOC); // 7-bit unsigned (0-100)
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
// Grammar 3: END_ELEMENT
|
||||
stream.WriteNBitUnsignedInteger(1, 0);
|
||||
stream.encodeNBitUnsignedInteger(1, 0);
|
||||
|
||||
// Console.Error.WriteLine($"🔍 [DC_EVStatus] Encoding completed, position: {stream.Position}");
|
||||
}
|
||||
@@ -613,28 +635,28 @@ namespace V2GDecoderNet.V2G
|
||||
private static void EncodePhysicalValueType(BitOutputStreamExact stream, PhysicalValueType value)
|
||||
{
|
||||
int posBefore = stream.Position;
|
||||
// Console.Error.WriteLine($"🔬 [PhysicalValue] Starting: M={value.Multiplier}, U={(int)value.Unit}, V={value.Value}, pos_before={posBefore}");
|
||||
Console.Error.WriteLine($"🔬 [PhysicalValue] Starting: M={value.Multiplier}, U={(int)value.Unit}, V={value.Value}, pos_before={posBefore}");
|
||||
|
||||
// Grammar 117: START_ELEMENT(Multiplier)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[NBIT_UNSIGNED_INTEGER]
|
||||
stream.WriteNBitUnsignedInteger(3, (int)(value.Multiplier + 3)); // 3-bit unsigned + 3 offset
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[NBIT_UNSIGNED_INTEGER]
|
||||
stream.encodeNBitUnsignedInteger(3, (int)(value.Multiplier + 3)); // 3-bit unsigned + 3 offset
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
// Grammar 118: START_ELEMENT(Unit)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION]
|
||||
stream.WriteNBitUnsignedInteger(3, (int)value.Unit); // 3-bit enumeration
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION]
|
||||
stream.encodeNBitUnsignedInteger(3, (int)value.Unit); // 3-bit enumeration
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
// Grammar 119: START_ELEMENT(Value)
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[INTEGER]
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[INTEGER]
|
||||
stream.WriteInteger16((short)value.Value); // VC2022 encodeInteger16
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
// Grammar 3: END_ELEMENT
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // END_ELEMENT
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // END_ELEMENT
|
||||
|
||||
int posAfter = stream.Position;
|
||||
// Console.Error.WriteLine($"🔬 [PhysicalValue] Completed: M={value.Multiplier}, U={(int)value.Unit}, V={value.Value}, pos_after={posAfter}, used_bytes={posAfter - posBefore}");
|
||||
@@ -646,9 +668,14 @@ namespace V2GDecoderNet.V2G
|
||||
/// </summary>
|
||||
private static void EncodeBooleanElement(BitOutputStreamExact stream, bool value)
|
||||
{
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[BOOLEAN]
|
||||
stream.WriteBit(value ? 1 : 0); // Boolean bit
|
||||
stream.WriteNBitUnsignedInteger(1, 0); // valid EE
|
||||
Console.Error.WriteLine($"🔍 [EncodeBooleanElement] pos={stream.Position}:{stream.BitPosition}, value={value}");
|
||||
|
||||
// Standard EXI boolean pattern: CHARACTERS[BOOLEAN] + value + EE
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[BOOLEAN] = 0
|
||||
stream.encodeNBitUnsignedInteger(1, value ? 1 : 0); // Boolean value
|
||||
stream.encodeNBitUnsignedInteger(1, 0); // valid EE
|
||||
|
||||
Console.Error.WriteLine($"🔍 [EncodeBooleanElement] pos after={stream.Position}:{stream.BitPosition}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -589,8 +589,8 @@ namespace V2GDecoderNet
|
||||
if (bulkChargingComplete != null)
|
||||
{
|
||||
req.BulkChargingComplete = bool.Parse(bulkChargingComplete.Value);
|
||||
// VC2022 behavior: ignore BulkChargingComplete element when value is false, keep _isUsed = false
|
||||
req.BulkChargingComplete_isUsed = req.BulkChargingComplete; // Only set to true if value is true
|
||||
// XML에서 요소가 명시적으로 포함되면 값과 관계없이 _isUsed = true
|
||||
req.BulkChargingComplete_isUsed = true; // Element exists in XML
|
||||
}
|
||||
|
||||
var chargingComplete = reqElement.Element(ns3 + "ChargingComplete");
|
||||
|
||||
275
Port/vc2022/UpgradeLog.htm
Normal file
275
Port/vc2022/UpgradeLog.htm
Normal file
@@ -0,0 +1,275 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- saved from url=(0014)about:internet -->
|
||||
<html xmlns:msxsl="urn:schemas-microsoft-com:xslt"><head><meta content="en-us" http-equiv="Content-Language" /><meta content="text/html; charset=utf-16" http-equiv="Content-Type" /><title _locID="ConversionReport0">
|
||||
마이그레이션 보고서
|
||||
</title><style>
|
||||
/* Body style, for the entire document */
|
||||
body
|
||||
{
|
||||
background: #F3F3F4;
|
||||
color: #1E1E1F;
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Header1 style, used for the main title */
|
||||
h1
|
||||
{
|
||||
padding: 10px 0px 10px 10px;
|
||||
font-size: 21pt;
|
||||
background-color: #E2E2E2;
|
||||
border-bottom: 1px #C1C1C2 solid;
|
||||
color: #201F20;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Header2 style, used for "Overview" and other sections */
|
||||
h2
|
||||
{
|
||||
font-size: 18pt;
|
||||
font-weight: normal;
|
||||
padding: 15px 0 5px 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Header3 style, used for sub-sections, such as project name */
|
||||
h3
|
||||
{
|
||||
font-weight: normal;
|
||||
font-size: 15pt;
|
||||
margin: 0;
|
||||
padding: 15px 0 5px 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* Color all hyperlinks one color */
|
||||
a
|
||||
{
|
||||
color: #1382CE;
|
||||
}
|
||||
|
||||
/* Table styles */
|
||||
table
|
||||
{
|
||||
border-spacing: 0 0;
|
||||
border-collapse: collapse;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
table th
|
||||
{
|
||||
background: #E7E7E8;
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
padding: 3px 6px 3px 6px;
|
||||
}
|
||||
|
||||
table td
|
||||
{
|
||||
vertical-align: top;
|
||||
padding: 3px 6px 5px 5px;
|
||||
margin: 0px;
|
||||
border: 1px solid #E7E7E8;
|
||||
background: #F7F7F8;
|
||||
}
|
||||
|
||||
/* Local link is a style for hyperlinks that link to file:/// content, there are lots so color them as 'normal' text until the user mouse overs */
|
||||
.localLink
|
||||
{
|
||||
color: #1E1E1F;
|
||||
background: #EEEEED;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.localLink:hover
|
||||
{
|
||||
color: #1382CE;
|
||||
background: #FFFF99;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Center text, used in the over views cells that contain message level counts */
|
||||
.textCentered
|
||||
{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* The message cells in message tables should take up all avaliable space */
|
||||
.messageCell
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Padding around the content after the h1 */
|
||||
#content
|
||||
{
|
||||
padding: 0px 12px 12px 12px;
|
||||
}
|
||||
|
||||
/* The overview table expands to width, with a max width of 97% */
|
||||
#overview table
|
||||
{
|
||||
width: auto;
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
/* The messages tables are always 97% width */
|
||||
#messages table
|
||||
{
|
||||
width: 97%;
|
||||
}
|
||||
|
||||
/* All Icons */
|
||||
.IconSuccessEncoded, .IconInfoEncoded, .IconWarningEncoded, .IconErrorEncoded
|
||||
{
|
||||
min-width:18px;
|
||||
min-height:18px;
|
||||
background-repeat:no-repeat;
|
||||
background-position:center;
|
||||
}
|
||||
|
||||
/* Success icon encoded */
|
||||
.IconSuccessEncoded
|
||||
{
|
||||
/* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */
|
||||
/* [---XsltValidateInternal-Base64EncodedImage:IconSuccess#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABcElEQVR4Xq2TsUsCURzHv15g8ZJcBWlyiYYgCIWcb9DFRRwMW5TA2c0/QEFwFkxxUQdxVlBwCYWOi6IhWgQhBLHJUCkhLr/BW8S7gvrAg+N+v8/v+x68Z8MGy+XSCyABQAXgBgHGALoASkIIDWSLeLBetdHryMjd5IxQPWT4rn1c/P7+xxp72Cs9m5SZ0Bq2vPnbPFafK2zDvmNHypdC0BPkLlQhxJsCAhQoZwdZU5mwxh720qGo8MzTxTTKZDPCx2HoVzp6lz0Q9tKhyx0kGs8Ny+TkWRKk8lCROwEduhyg9l/6lunOPSfmH3NUH6uQ0KHLAe7JYvJjevm+DAMGJHToKtigE+vwvIidxLamb8IBY9e+C5LiXREkfho3TSd06HJA13/oh6T51MTsfQbHrsMynQ5dDihFjiK8JJAU9AKIWTp76dCVN7HWHrajmUEGvyF9nkbAE6gLIS7kTUyuf2gscLoJrElZo/Mvj+nPz/kLTmfnEwP3tB0AAAAASUVORK5CYII=);
|
||||
}
|
||||
|
||||
/* Information icon encoded */
|
||||
.IconInfoEncoded
|
||||
{
|
||||
/* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */
|
||||
/* [---XsltValidateInternal-Base64EncodedImage:IconInformation#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR4Xs2TsUoDQRRF7wwoziokjZUKadInhdhukR9YP8DMX1hYW+QvdsXa/QHBbcXC7W0CamWTQnclFutceIQJwwaWNLlwm5k5d94M76mmaeCrrmsLYOocY12FcxZFUeozCqKqqgYA8uevv1H6VuPxcwlfk5N92KHBxfFeCSAxxswlYAW/Xr989x/mv9gkhtyMDhcAxgzRsp7flj8B/HF1RsMXq+NZMkopaHe7lbKxQUEIGbKsYNoGn969060hZBkQex/W8oRQwsQaW2o3Ago2SVcJUzAgY3N0lTCZZm+zPS8HB51gMmS1DEYyOz9acKO1D8JWTlafKIMxdhvlfdyT94Vv5h7P8Ky7nQzACmhvKq3zk3PjW9asz9D/1oigecsioooAAAAASUVORK5CYII=);
|
||||
}
|
||||
|
||||
/* Warning icon encoded */
|
||||
.IconWarningEncoded
|
||||
{
|
||||
/* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */
|
||||
/* [---XsltValidateInternal-Base64EncodedImage:IconWarning#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAx0lEQVR4XpWSMQ7CMAxFf4xAyBMLCxMrO8dhaBcuwdCJS3RJBw7SA/QGTCxdWJgiQYWKXJWKIXHIlyw5lqr34tQgEOdcBsCOx5yZK3hCCKdYXneQkh4pEfqzLfu+wVDSyyzFoJjfz9NB+pAF+eizx2Vruts0k15mPgvS6GYvpVtQhB61IB/dk6AF6fS4Ben0uIX5odtFe8Q/eW1KvFeH4e8khT6+gm5B+t3juyDt7n0jpe+CANTd+oTUjN/U3yVaABnSUjFz/gFq44JaVSCXeQAAAABJRU5ErkJggg==);
|
||||
}
|
||||
|
||||
/* Error icon encoded */
|
||||
.IconErrorEncoded
|
||||
{
|
||||
/* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */
|
||||
/* [---XsltValidateInternal-Base64EncodedImage:IconError#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABQElEQVR4XqWTvUoEQRCE6wYPZUA80AfwAQz23uCMjA7MDRQEIzPBVEyNTQUFIw00vcQTTMzuAh/AxEQQT8HF/3G/oGGnEUGuoNnd6qoZuqltyKEsyzVJq5I6rnUp6SjGeGhESikzzlc1eL7opfuVbrqbU1Zw9NCgtQMaZpY0eNnaaL2fHusvTK5vKu7sjSS1Y4y3QUA6K3e3Mau5UFDyMP7tYF9o8cAHZv68vipoIJg971PZIZ5HiwdvYGGvFVFHmGmZ2MxwmQYPXubPl9Up0tfoMQGetXd6mRbvhBw+boZ6WF7Mbv1+GsHRk0fQmPAH1GfmZirbCfDJ61tw3Px8/8pZsPAG4jlVhcPgZ7adwNWBB68lkRQWFiTgFlbnLY3DGGM7izIJIyT/jjIvEJw6fdJTc6krDzh6aMwMP9bvDH4ADSsa9uSWVJkAAAAASUVORK5CYII=);
|
||||
}
|
||||
</style><script type="text/javascript" language="javascript">
|
||||
|
||||
// Startup
|
||||
// Hook up the the loaded event for the document/window, to linkify the document content
|
||||
var startupFunction = function() { linkifyElement("messages"); };
|
||||
|
||||
if(window.attachEvent)
|
||||
{
|
||||
window.attachEvent('onload', startupFunction);
|
||||
}
|
||||
else if (window.addEventListener)
|
||||
{
|
||||
window.addEventListener('load', startupFunction, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
document.addEventListener('load', startupFunction, false);
|
||||
}
|
||||
|
||||
// Toggles the visibility of table rows with the specified name
|
||||
function toggleTableRowsByName(name)
|
||||
{
|
||||
var allRows = document.getElementsByTagName('tr');
|
||||
for (i=0; i < allRows.length; i++)
|
||||
{
|
||||
var currentName = allRows[i].getAttribute('name');
|
||||
if(!!currentName && currentName.indexOf(name) == 0)
|
||||
{
|
||||
var isVisible = allRows[i].style.display == '';
|
||||
isVisible ? allRows[i].style.display = 'none' : allRows[i].style.display = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToFirstVisibleRow(name)
|
||||
{
|
||||
var allRows = document.getElementsByTagName('tr');
|
||||
for (i=0; i < allRows.length; i++)
|
||||
{
|
||||
var currentName = allRows[i].getAttribute('name');
|
||||
var isVisible = allRows[i].style.display == '';
|
||||
if(!!currentName && currentName.indexOf(name) == 0 && isVisible)
|
||||
{
|
||||
allRows[i].scrollIntoView(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Linkifies the specified text content, replaces candidate links with html links
|
||||
function linkify(text)
|
||||
{
|
||||
if(!text || 0 === text.length)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
// Find http, https and ftp links and replace them with hyper links
|
||||
var urlLink = /(http|https|ftp)\:\/\/[a-zA-Z0-9\-\.]+(:[a-zA-Z0-9]*)?\/?([a-zA-Z0-9\-\._\?\,\/\\\+&%\$#\=~;\{\}])*/gi;
|
||||
|
||||
return text.replace(urlLink, '<a href="$&">$&</a>') ;
|
||||
}
|
||||
|
||||
// Linkifies the specified element by ID
|
||||
function linkifyElement(id)
|
||||
{
|
||||
var element = document.getElementById(id);
|
||||
if(!!element)
|
||||
{
|
||||
element.innerHTML = linkify(element.innerHTML);
|
||||
}
|
||||
}
|
||||
|
||||
function ToggleMessageVisibility(projectName)
|
||||
{
|
||||
if(!projectName || 0 === projectName.length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
toggleTableRowsByName("MessageRowClass" + projectName);
|
||||
toggleTableRowsByName('MessageRowHeaderShow' + projectName);
|
||||
toggleTableRowsByName('MessageRowHeaderHide' + projectName);
|
||||
}
|
||||
|
||||
function ScrollToFirstVisibleMessage(projectName)
|
||||
{
|
||||
if(!projectName || 0 === projectName.length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// First try the 'Show messages' row
|
||||
if(!scrollToFirstVisibleRow('MessageRowHeaderShow' + projectName))
|
||||
{
|
||||
// Failed to find a visible row for 'Show messages', try an actual message row
|
||||
scrollToFirstVisibleRow('MessageRowClass' + projectName);
|
||||
}
|
||||
}
|
||||
</script></head><body><h1 _locID="ConversionReport">
|
||||
마이그레이션 보고서 - </h1><div id="content"><h2 _locID="OverviewTitle">개요</h2><div id="overview"><table><tr><th></th><th _locID="ProjectTableHeader">프로젝트</th><th _locID="PathTableHeader">경로</th><th _locID="ErrorsTableHeader">오류</th><th _locID="WarningsTableHeader">경고</th><th _locID="MessagesTableHeader">메시지</th></tr><tr><td class="IconErrorEncoded" /><td><strong><a href="#HexDumpToBinary">HexDumpToBinary</a></strong></td><td>HexDumpToBinary\HexDumpToBinary.vcxproj</td><td class="textCentered"><a href="#HexDumpToBinaryError">1</a></td><td class="textCentered"><a>0</a></td><td class="textCentered"><a href="#">0</a></td></tr><tr><td class="IconErrorEncoded" /><td><strong><a href="#HexToBinary">HexToBinary</a></strong></td><td>HexToBinary\HexToBinary.vcxproj</td><td class="textCentered"><a href="#HexToBinaryError">1</a></td><td class="textCentered"><a>0</a></td><td class="textCentered"><a href="#">0</a></td></tr><tr><td class="IconErrorEncoded" /><td><strong><a href="#V2GDecoder">V2GDecoder</a></strong></td><td>V2GDecoder\V2GDecoder.vcxproj</td><td class="textCentered"><a href="#V2GDecoderError">1</a></td><td class="textCentered"><a>0</a></td><td class="textCentered"><a href="#">0</a></td></tr><tr><td class="IconSuccessEncoded" /><td><strong><a href="#Solution"><span _locID="OverviewSolutionSpan">솔루션</span></a></strong></td><td>V2GDecoderC.sln</td><td class="textCentered"><a>0</a></td><td class="textCentered"><a>0</a></td><td class="textCentered"><a href="#" onclick="ScrollToFirstVisibleMessage('Solution'); return false;">1</a></td></tr></table></div><h2 _locID="SolutionAndProjectsTitle">솔루션 및 프로젝트</h2><div id="messages"><a name="HexDumpToBinary" /><h3>HexDumpToBinary</h3><table><tr id="HexDumpToBinaryHeaderRow"><th></th><th class="messageCell" _locID="MessageTableHeader">메시지</th></tr><tr name="ErrorRowClassHexDumpToBinary"><td class="IconErrorEncoded"><a name="HexDumpToBinaryError" /></td><td class="messageCell"><strong>HexDumpToBinary\HexDumpToBinary.vcxproj:
|
||||
</strong><span>이 프로젝트 형식을 기반으로 하는 애플리케이션을 찾지 못했습니다. 추가 정보를 보려면 이 링크를 확인하십시오. 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942</span></td></tr></table><a name="HexToBinary" /><h3>HexToBinary</h3><table><tr id="HexToBinaryHeaderRow"><th></th><th class="messageCell" _locID="MessageTableHeader">메시지</th></tr><tr name="ErrorRowClassHexToBinary"><td class="IconErrorEncoded"><a name="HexToBinaryError" /></td><td class="messageCell"><strong>HexToBinary\HexToBinary.vcxproj:
|
||||
</strong><span>이 프로젝트 형식을 기반으로 하는 애플리케이션을 찾지 못했습니다. 추가 정보를 보려면 이 링크를 확인하십시오. 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942</span></td></tr></table><a name="V2GDecoder" /><h3>V2GDecoder</h3><table><tr id="V2GDecoderHeaderRow"><th></th><th class="messageCell" _locID="MessageTableHeader">메시지</th></tr><tr name="ErrorRowClassV2GDecoder"><td class="IconErrorEncoded"><a name="V2GDecoderError" /></td><td class="messageCell"><strong>V2GDecoder\V2GDecoder.vcxproj:
|
||||
</strong><span>이 프로젝트 형식을 기반으로 하는 애플리케이션을 찾지 못했습니다. 추가 정보를 보려면 이 링크를 확인하십시오. 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942</span></td></tr></table><a name="Solution" /><h3 _locID="ProjectDisplayNameHeader">솔루션</h3><table><tr id="SolutionHeaderRow"><th></th><th class="messageCell" _locID="MessageTableHeader">메시지</th></tr><tr name="MessageRowHeaderShowSolution"><td class="IconInfoEncoded" /><td class="messageCell"><a _locID="ShowAdditionalMessages" href="#" name="SolutionMessage" onclick="ToggleMessageVisibility('Solution'); return false;">
|
||||
표시 1 추가 메시지
|
||||
</a></td></tr><tr name="MessageRowClassSolution" style="display: none"><td class="IconInfoEncoded"><a name="SolutionMessage" /></td><td class="messageCell"><strong>V2GDecoderC.sln:
|
||||
</strong><span>솔루션 파일은 마이그레이션하지 않아도 됩니다.</span></td></tr><tr style="display: none" name="MessageRowHeaderHideSolution"><td class="IconInfoEncoded" /><td class="messageCell"><a _locID="HideAdditionalMessages" href="#" name="SolutionMessage" onclick="ToggleMessageVisibility('Solution'); return false;">
|
||||
숨기기 1 추가 메시지
|
||||
</a></td></tr></table></div></div></body></html>
|
||||
@@ -831,7 +831,7 @@ void dump_iso1_document_to_file(const struct iso1EXIDocument* doc, const char* f
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
printf("✓ Structure dump saved to %s\n", filename);
|
||||
DEBUG_PRINTF(("✓ Structure dump saved to %s\n", filename));
|
||||
}
|
||||
|
||||
// Helper function to convert hex string to binary
|
||||
@@ -1146,7 +1146,7 @@ void print_iso1_message(struct iso1EXIDocument* doc) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("DEBUG: argc=%d\n", argc);
|
||||
DEBUG_PRINTF(("DEBUG: argc=%d\n", argc));
|
||||
int xml_mode = 0;
|
||||
int encode_mode = 0;
|
||||
char *filename = NULL;
|
||||
@@ -1179,16 +1179,17 @@ int main(int argc, char *argv[]) {
|
||||
encode_mode = 1;
|
||||
filename = argv[arg_index + 1];
|
||||
} else {
|
||||
printf("Usage: %s [-debug] [-decode|-encode] input_file\\n", argv[0]);
|
||||
printf(" %s [-debug] -encode (read XML from stdin)\\n", argv[0]);
|
||||
printf(" %s [-debug] -decode (read hex string from stdin)\\n", argv[0]);
|
||||
printf("Usage: V2GDecoder [-debug] [-decode|-encode] input_file\\n");
|
||||
printf(" V2GDecoder [-debug] -encode (read XML from stdin)\\n");
|
||||
printf(" V2GDecoder [-debug] -decode (read hex string from stdin)\\n");
|
||||
printf("Enhanced EXI viewer with XML conversion capabilities\\n");
|
||||
printf(" -debug Enable detailed bit-level encoding/decoding output\\n");
|
||||
printf(" -decode Convert EXI to Wireshark-style XML format\\n");
|
||||
printf(" -decode Read hex string from stdin (echo hex | %s -decode)\\n", argv[0]);
|
||||
printf(" -decode Read hex string from stdin (echo hex | V2GDecoder -decode)\\n");
|
||||
printf(" -encode Convert XML to EXI format\\n");
|
||||
printf(" -encode Read XML from stdin (type file.xml | %s -encode)\\n", argv[0]);
|
||||
printf(" -encode Read XML from stdin (type file.xml | V2GDecoder -encode)\\n");
|
||||
printf(" (default) Analyze EXI with detailed output\\n");
|
||||
printf("\\nContact: tindevil82@gmail.com\\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1208,7 +1209,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Handle encode mode (XML to EXI)
|
||||
if (encode_mode) {
|
||||
fprintf(stderr, "DEBUG: Entering encode mode\n");
|
||||
DEBUG_PRINTF(("DEBUG: Entering encode mode\n"));
|
||||
FILE* xml_file;
|
||||
char* xml_content;
|
||||
long xml_size;
|
||||
@@ -1266,9 +1267,9 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Parse XML to ISO1 document structure
|
||||
fprintf(stderr, "DEBUG: About to parse XML content\n");
|
||||
DEBUG_PRINTF(("DEBUG: About to parse XML content\n"));
|
||||
int parse_result = parse_xml_to_iso1(xml_content, &iso1Doc);
|
||||
fprintf(stderr, "DEBUG: XML parse result: %d\n", parse_result);
|
||||
DEBUG_PRINTF(("DEBUG: XML parse result: %d\n", parse_result));
|
||||
if (parse_result != 0) {
|
||||
printf("Error parsing XML file - no supported message type found\\n");
|
||||
free(xml_content);
|
||||
@@ -1284,17 +1285,17 @@ int main(int argc, char *argv[]) {
|
||||
// Debug output disabled for clean hex-only output
|
||||
|
||||
if (iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed) {
|
||||
fprintf(stderr, "EVReady: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false");
|
||||
fprintf(stderr, "EVErrorCode: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode);
|
||||
fprintf(stderr, "EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC);
|
||||
fprintf(stderr, "EVTargetCurrent: M=%d, U=%d, V=%d\\n",
|
||||
DEBUG_PRINTF(("EVReady: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false"));
|
||||
DEBUG_PRINTF(("EVErrorCode: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode));
|
||||
DEBUG_PRINTF(("EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC));
|
||||
DEBUG_PRINTF(("EVTargetCurrent: M=%d, U=%d, V=%d\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier,
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit,
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value);
|
||||
fprintf(stderr, "EVTargetVoltage: M=%d, U=%d, V=%d\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value));
|
||||
DEBUG_PRINTF(("EVTargetVoltage: M=%d, U=%d, V=%d\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier,
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit,
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value);
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value));
|
||||
}
|
||||
|
||||
|
||||
@@ -1309,9 +1310,11 @@ int main(int argc, char *argv[]) {
|
||||
stream.capacity = 0;
|
||||
|
||||
// 구조체 덤프 (디버그용, 필요시 활성화)
|
||||
fprintf(stderr, "DEBUG: About to dump structure to temp/struct_xml.txt\n");
|
||||
DEBUG_PRINTF(("DEBUG: About to dump structure to temp/struct_xml.txt\n"));
|
||||
if (EXI_DEBUG_MODE) {
|
||||
dump_iso1_document_to_file(&iso1Doc, "temp/struct_xml.txt");
|
||||
fprintf(stderr, "DEBUG: Structure dump completed\n");
|
||||
}
|
||||
DEBUG_PRINTF(("DEBUG: Structure dump completed\n"));
|
||||
|
||||
errn = encode_iso1ExiDocument(&stream, &iso1Doc);
|
||||
|
||||
@@ -1422,31 +1425,31 @@ int main(int argc, char *argv[]) {
|
||||
print_iso1_message(&iso1Doc);
|
||||
|
||||
// Compare with expected structure
|
||||
printf("\\n=== Original EXI Structure Debug ===\\n");
|
||||
printf("V2G_Message_isUsed: %s\\n", iso1Doc.V2G_Message_isUsed ? "true" : "false");
|
||||
printf("SessionID length: %d\\n", iso1Doc.V2G_Message.Header.SessionID.bytesLen);
|
||||
printf("CurrentDemandReq_isUsed: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed ? "true" : "false");
|
||||
DEBUG_PRINTF(("\\n=== Original EXI Structure Debug ===\\n"));
|
||||
DEBUG_PRINTF(("V2G_Message_isUsed: %s\\n", iso1Doc.V2G_Message_isUsed ? "true" : "false"));
|
||||
DEBUG_PRINTF(("SessionID length: %d\\n", iso1Doc.V2G_Message.Header.SessionID.bytesLen));
|
||||
DEBUG_PRINTF(("CurrentDemandReq_isUsed: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed ? "true" : "false"));
|
||||
|
||||
if (iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed) {
|
||||
printf("EVReady: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false");
|
||||
printf("EVErrorCode: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode);
|
||||
printf("EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC);
|
||||
printf("EVTargetCurrent: M=%d, U=%d, V=%d\\n",
|
||||
DEBUG_PRINTF(("EVReady: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false"));
|
||||
DEBUG_PRINTF(("EVErrorCode: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode));
|
||||
DEBUG_PRINTF(("EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC));
|
||||
DEBUG_PRINTF(("EVTargetCurrent: M=%d, U=%d, V=%d\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier,
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit,
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value);
|
||||
printf("EVMaximumVoltageLimit_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed ? "true" : "false");
|
||||
printf("EVMaximumCurrentLimit_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed ? "true" : "false");
|
||||
printf("EVMaximumPowerLimit_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed ? "true" : "false");
|
||||
printf("BulkChargingComplete_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed ? "true" : "false");
|
||||
printf("RemainingTimeToFullSoC_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed ? "true" : "false");
|
||||
printf("RemainingTimeToBulkSoC_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed ? "true" : "false");
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value));
|
||||
DEBUG_PRINTF(("EVMaximumVoltageLimit_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed ? "true" : "false"));
|
||||
DEBUG_PRINTF(("EVMaximumCurrentLimit_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed ? "true" : "false"));
|
||||
DEBUG_PRINTF(("EVMaximumPowerLimit_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed ? "true" : "false"));
|
||||
DEBUG_PRINTF(("BulkChargingComplete_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed ? "true" : "false"));
|
||||
DEBUG_PRINTF(("RemainingTimeToFullSoC_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed ? "true" : "false"));
|
||||
DEBUG_PRINTF(("RemainingTimeToBulkSoC_isUsed: %s\\n",
|
||||
iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed ? "true" : "false"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
V2GDecoder.exe
BIN
V2GDecoder.exe
Binary file not shown.
94
docs/final_comparison_clean.md
Normal file
94
docs/final_comparison_clean.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# V2G EXI Decoder - 최종 Clean Output 비교 결과
|
||||
|
||||
## 요구사항 달성 상태
|
||||
|
||||
✅ **VC2022 버전 완성**
|
||||
- ✅ -decode 옵션: 순수 XML만 출력 (디버그 메시지 제거)
|
||||
- ✅ -encode 옵션: 순수 hex string 출력 (디버그 메시지 제거)
|
||||
- ✅ Usage 메시지: dotnet 버전과 동일한 형식
|
||||
- ✅ 모든 샘플 파일(test1-5.exi) 테스트 완료
|
||||
|
||||
## VC2022 버전 테스트 결과
|
||||
|
||||
### -decode 테스트
|
||||
모든 샘플에 대해 순수 XML만 출력:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ns1:V2G_Message xmlns:ns1="urn:iso:15118:2:2013:MsgDef" xmlns:ns2="urn:iso:15118:2:2013:MsgHeader" xmlns:ns3="urn:iso:15118:2:2013:MsgBody" xmlns:ns4="urn:iso:15118:2:2013:MsgDataTypes">
|
||||
<ns1:Header><ns2:SessionID>4142423030303831</ns2:SessionID></ns1:Header>
|
||||
<ns1:Body>...</ns1:Body>
|
||||
</ns1:V2G_Message>
|
||||
```
|
||||
|
||||
### -encode 테스트
|
||||
모든 라운드트립에 대해 순수 hex string만 출력:
|
||||
```
|
||||
# test1.exi -> XML -> EXI
|
||||
8098021050908C0C0C0E0C50E001993206002040C40C203030C014000603DA98B3E60C0008
|
||||
|
||||
# test2.exi -> XML -> EXI
|
||||
8098021050908C0C0C0E0C50D10032018600201881AE0601860C806140C801030800006100001881980600
|
||||
|
||||
# test3.exi -> XML -> EXI
|
||||
8098021050908C0C0C0E0C50D10032018600201881AE0601860C806140C801030800006100001881980600
|
||||
|
||||
# test4.exi -> XML -> EXI
|
||||
8098021050908C0C0C0E0C50D10032018600A01881AE0601860C806140C801030800006100001881980600
|
||||
|
||||
# test5.exi -> XML -> EXI
|
||||
8098021050908C0C0C0E0C50D10032018600201881AE0601860C806140C801030800006100001881980600
|
||||
```
|
||||
|
||||
### Usage 메시지 (옵션 없이 실행)
|
||||
```
|
||||
Usage: V2GDecoder [-debug] [-decode|-encode] input_file
|
||||
V2GDecoder [-debug] -encode (read XML from stdin)
|
||||
V2GDecoder [-debug] -decode (read hex string from stdin)
|
||||
Enhanced EXI viewer with XML conversion capabilities
|
||||
-debug Enable detailed bit-level encoding/decoding output
|
||||
-decode Convert EXI to Wireshark-style XML format
|
||||
-decode Read hex string from stdin (echo hex | V2GDecoder -decode)
|
||||
-encode Convert XML to EXI format
|
||||
-encode Read XML from stdin (type file.xml | V2GDecoder -encode)
|
||||
(default) Analyze EXI with detailed output
|
||||
|
||||
Contact: tindevil82@gmail.com
|
||||
```
|
||||
|
||||
## 구현 방법
|
||||
|
||||
### DEBUG_PRINTF 매크로 활용
|
||||
기존 코드의 `DEBUG_PRINTF` 매크로를 활용하여 모든 디버그 출력을 조건부로 변경:
|
||||
|
||||
```c
|
||||
// 변경 전
|
||||
printf("DEBUG: argc=%d\\n", argc);
|
||||
fprintf(stderr, "EVReady: %s\\n", ...);
|
||||
|
||||
// 변경 후
|
||||
DEBUG_PRINTF(("DEBUG: argc=%d\\n", argc));
|
||||
DEBUG_PRINTF(("EVReady: %s\\n", ...));
|
||||
```
|
||||
|
||||
### 조건부 디버그 모드
|
||||
- `EXI_DEBUG_MODE`가 활성화된 경우에만 디버그 출력
|
||||
- -debug 플래그로 사용자가 원할 때만 상세 출력 활성화
|
||||
- -decode/-encode 전용 모드에서는 완전히 깨끗한 출력
|
||||
|
||||
## 결론
|
||||
|
||||
✅ **목표 달성**: VC2022 버전이 dotnet 버전과 동일하게 깨끗한 출력을 제공합니다.
|
||||
✅ **호환성**: 두 버전 모두 동일한 XML 출력 및 EXI 인코딩 결과
|
||||
✅ **사용자 경험**: -decode/-encode 옵션에서 "쓸데없는 메시지" 완전 제거
|
||||
✅ **유연성**: -debug 옵션으로 필요시 상세 분석 가능
|
||||
|
||||
## 빌드 및 실행
|
||||
```bash
|
||||
# 빌드
|
||||
cd Port/vc2022
|
||||
./build.bat
|
||||
|
||||
# 사용
|
||||
V2GDecoder.exe -decode sample/test5.exi
|
||||
V2GDecoder.exe -debug -decode sample/test5.exi # 디버그 정보 포함
|
||||
```
|
||||
102
docs/message_implementation_status_report.md
Normal file
102
docs/message_implementation_status_report.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# V2G EXI Decoder - 메시지 구현 상태 최종 리포트
|
||||
|
||||
## 구현 상태 요약
|
||||
|
||||
### ✅ 완전 구현된 메시지 (모든 버전)
|
||||
| 메시지 타입 | 오리지널 C | VC2022 | dotnet | 비고 |
|
||||
|------------|-----------|---------|--------|------|
|
||||
| CurrentDemandReq | ✅ | ✅ | ✅ | XML파싱/생성, EXI인코딩/디코딩 완료 |
|
||||
| CurrentDemandRes | ✅ | ✅ | ✅ | XML파싱/생성, EXI인코딩/디코딩 완료 |
|
||||
|
||||
### 📋 구조체는 있지만 로직 미구현 (높은 우선순위)
|
||||
|
||||
#### DC 충전 필수 메시지들
|
||||
| 메시지 타입 | 오리지널 C | VC2022 | dotnet | ISO 15118-2 필수 여부 |
|
||||
|------------|-----------|---------|--------|-------------------|
|
||||
| CableCheckReq/Res | ❌ | 📋 | 📋 | **필수** - DC 충전 시작 전 케이블 절연 확인 |
|
||||
| PreChargeReq/Res | ❌ | 📋 | 📋 | **필수** - DC 충전 시작 전 사전충전 |
|
||||
| WeldingDetectionReq/Res | ❌ | 📋 | 📋 | **필수** - DC 충전 종료 후 용접 검출 |
|
||||
|
||||
#### 전력 제어 메시지
|
||||
| 메시지 타입 | 오리지널 C | VC2022 | dotnet | ISO 15118-2 필수 여부 |
|
||||
|------------|-----------|---------|--------|-------------------|
|
||||
| PowerDeliveryReq/Res | ❌ | 📋 | 📋 | **필수** - 충전 시작/중지 제어 |
|
||||
|
||||
#### 세션 관리 메시지
|
||||
| 메시지 타입 | 오리지널 C | VC2022 | dotnet | ISO 15118-2 필수 여부 |
|
||||
|------------|-----------|---------|--------|-------------------|
|
||||
| SessionSetupReq/Res | ❌ | 📋 | 📋 | **필수** - 충전 세션 설정 |
|
||||
| SessionStopReq/Res | ❌ | 📋 | 📋 | 권장 - 충전 세션 종료 |
|
||||
|
||||
#### 서비스 검색 메시지
|
||||
| 메시지 타입 | 오리지널 C | VC2022 | dotnet | ISO 15118-2 필수 여부 |
|
||||
|------------|-----------|---------|--------|-------------------|
|
||||
| ServiceDiscoveryReq/Res | ❌ | 📋 | 📋 | **필수** - 충전 서비스 검색 |
|
||||
| ServiceDetailReq/Res | ❌ | 📋 | 📋 | 선택적 - 서비스 상세 정보 |
|
||||
|
||||
#### 인증 및 결제 메시지
|
||||
| 메시지 타입 | 오리지널 C | VC2022 | dotnet | ISO 15118-2 필수 여부 |
|
||||
|------------|-----------|---------|--------|-------------------|
|
||||
| AuthorizationReq/Res | ❌ | 📋 | 📋 | **필수** - 충전 권한 확인 |
|
||||
| ChargeParameterDiscoveryReq/Res | ❌ | 📋 | 📋 | **필수** - 충전 매개변수 교환 |
|
||||
| PaymentServiceSelectionReq/Res | ❌ | 📋 | 📋 | **필수** - 결제 서비스 선택 |
|
||||
| PaymentDetailsReq/Res | ❌ | 📋 | 📋 | 조건부 필수 - PnC 시 필요 |
|
||||
|
||||
#### AC 충전 메시지
|
||||
| 메시지 타입 | 오리지널 C | VC2022 | dotnet | ISO 15118-2 필수 여부 |
|
||||
|------------|-----------|---------|--------|-------------------|
|
||||
| ChargingStatusReq/Res | ❌ | 📋 | 📋 | AC 충전시 필수 |
|
||||
|
||||
#### 계량 및 인증서 메시지
|
||||
| 메시지 타입 | 오리지널 C | VC2022 | dotnet | ISO 15118-2 필수 여부 |
|
||||
|------------|-----------|---------|--------|-------------------|
|
||||
| MeteringReceiptReq/Res | ❌ | 📋 | 📋 | 선택적 - 계량 영수증 |
|
||||
| CertificateUpdateReq/Res | ❌ | 📋 | 📋 | 선택적 - 인증서 업데이트 |
|
||||
| CertificateInstallationReq/Res | ❌ | 📋 | 📋 | 선택적 - 인증서 설치 |
|
||||
|
||||
## 상태 기호 설명
|
||||
- ✅ **완전 구현**: XML 파싱/생성 + EXI 인코딩/디코딩 + 테스트 완료
|
||||
- 📋 **구조체만 존재**: EXI 구조체 정의되어 있으나 XML 파싱/생성 로직 미구현
|
||||
- ❌ **미구현**: 구조체는 있지만 실제 처리 로직 없음
|
||||
|
||||
## 기술적 발견사항
|
||||
|
||||
### 1. dotnet 버전의 구조적 우위
|
||||
- **다중 표준 지원**: ISO1, ISO2, DIN 표준별 구조체 분리
|
||||
- **확장성**: 새 메시지 타입 추가가 용이한 구조
|
||||
- **타입 안정성**: C# 강타입 시스템의 장점
|
||||
|
||||
### 2. VC2022 버전의 현황
|
||||
- **구조체 완성도**: 모든 ISO1 메시지 구조체 포함
|
||||
- **디버그 인프라**: DEBUG_PRINTF 시스템으로 일관성 유지
|
||||
- **C 호환성**: 오리지널 C 코드와 완전 호환
|
||||
|
||||
### 3. 오리지널 C 코드의 한계
|
||||
- **단일 메시지 집중**: CurrentDemand 메시지에만 특화
|
||||
- **확장성 부족**: 새 메시지 추가가 복잡함
|
||||
- **기본 인프라**: EXI 인코딩/디코딩 엔진은 완성도 높음
|
||||
|
||||
## 개발 우선순위 권장사항
|
||||
|
||||
### Phase 1 (최고 우선순위): DC 충전 핵심 4개 메시지
|
||||
1. **CableCheckReq/Res** - 케이블 절연 상태 확인
|
||||
2. **PreChargeReq/Res** - 사전 충전 전압 매칭
|
||||
3. **WeldingDetectionReq/Res** - 충전 종료 후 용접 검출
|
||||
4. **PowerDeliveryReq/Res** - 충전 시작/중지 제어
|
||||
|
||||
### Phase 2 (높은 우선순위): 세션 및 서비스
|
||||
5. **SessionSetupReq/Res** - 세션 설정
|
||||
6. **ServiceDiscoveryReq/Res** - 서비스 검색
|
||||
7. **ChargeParameterDiscoveryReq/Res** - 충전 매개변수
|
||||
8. **AuthorizationReq/Res** - 권한 확인
|
||||
|
||||
### Phase 3 (중간 우선순위): 결제 및 확장
|
||||
9. **PaymentServiceSelectionReq/Res** - 결제 서비스
|
||||
10. **ChargingStatusReq/Res** - AC 충전 상태
|
||||
11. **SessionStopReq/Res** - 세션 종료
|
||||
|
||||
## 결론
|
||||
|
||||
현재 V2G EXI Decoder는 **기본적인 DC 충전 인프라**(CurrentDemand)는 완성되어 있으나, **완전한 ISO 15118-2 호환성**을 위해서는 **최소 8개의 핵심 메시지 구현**이 추가로 필요합니다.
|
||||
|
||||
다행히 VC2022와 dotnet 버전에는 모든 메시지의 구조체가 준비되어 있어, **XML 파싱/생성 로직**만 추가하면 빠른 구현이 가능한 상태입니다.
|
||||
92
docs/v2g_message_support_analysis.md
Normal file
92
docs/v2g_message_support_analysis.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# V2G EXI Decoder - 메시지 타입 지원 현황 분석
|
||||
|
||||
## 오리지널 C 프로그램이 지원하는 메시지 타입 (우선순위 순)
|
||||
|
||||
### 1. 세션 관리 메시지 (Session Management)
|
||||
1. **SessionSetupReq/Res** - 충전 세션 설정
|
||||
2. **SessionStopReq/Res** - 충전 세션 종료
|
||||
|
||||
### 2. 서비스 검색 및 선택 (Service Discovery & Selection)
|
||||
3. **ServiceDiscoveryReq/Res** - 사용 가능한 충전 서비스 검색
|
||||
4. **ServiceDetailReq/Res** - 특정 서비스 상세 정보 요청
|
||||
5. **PaymentServiceSelectionReq/Res** - 결제 방식 및 서비스 선택
|
||||
|
||||
### 3. 인증 및 권한 (Authentication & Authorization)
|
||||
6. **AuthorizationReq/Res** - 충전 권한 확인
|
||||
7. **PaymentDetailsReq/Res** - 결제 정보 교환
|
||||
|
||||
### 4. 충전 매개변수 검색 (Charge Parameter Discovery)
|
||||
8. **ChargeParameterDiscoveryReq/Res** - 충전 매개변수 교환
|
||||
|
||||
### 5. DC 충전 특화 메시지 (DC Charging Specific) - 핵심 구현 필요
|
||||
9. **CableCheckReq/Res** ❌ - 케이블 연결 상태 확인 (미구현)
|
||||
10. **PreChargeReq/Res** ❌ - 사전 충전 (미구현)
|
||||
11. **CurrentDemandReq/Res** ✅ - 전류 요구사항 (구현됨)
|
||||
12. **WeldingDetectionReq/Res** ❌ - 용접 검출 (미구현)
|
||||
|
||||
### 6. AC 충전 특화 메시지 (AC Charging Specific)
|
||||
13. **ChargingStatusReq/Res** ❌ - AC 충전 상태 (미구현)
|
||||
|
||||
### 7. 전력 전달 제어 (Power Delivery Control)
|
||||
14. **PowerDeliveryReq/Res** ❌ - 전력 전달 제어 (미구현)
|
||||
|
||||
### 8. 계량 및 수납 (Metering & Billing)
|
||||
15. **MeteringReceiptReq/Res** ❌ - 계량 영수증 (미구현)
|
||||
|
||||
### 9. 인증서 관리 (Certificate Management)
|
||||
16. **CertificateUpdateReq/Res** ❌ - 인증서 업데이트 (미구현)
|
||||
17. **CertificateInstallationReq/Res** ❌ - 인증서 설치 (미구현)
|
||||
|
||||
## 현재 구현 상태 요약
|
||||
|
||||
### ✅ 구현된 메시지 (오리지널 C)
|
||||
- **CurrentDemandReq** - 완전 구현 (XML 파싱/생성, EXI 인코딩/디코딩)
|
||||
- **CurrentDemandRes** - 완전 구현 (XML 파싱/생성, EXI 인코딩/디코딩)
|
||||
|
||||
### ❌ 미구현 메시지 (필수 DC 충전 메시지들)
|
||||
1. **CableCheckReq/Res** - DC 충전 시작 전 케이블 절연 상태 확인
|
||||
2. **PreChargeReq/Res** - DC 충전 시작 전 사전충전으로 전압 매칭
|
||||
3. **WeldingDetectionReq/Res** - DC 충전 종료 후 용접 상태 확인
|
||||
4. **PowerDeliveryReq/Res** - 충전 시작/중지 명령
|
||||
|
||||
## 권장 구현 순서 (C → VC → dotnet)
|
||||
|
||||
### Phase 1: DC 충전 핵심 메시지 (높은 우선순위)
|
||||
1. **CableCheckReq/Res** - ISO 15118-2 DC 충전 필수 메시지
|
||||
2. **PreChargeReq/Res** - ISO 15118-2 DC 충전 필수 메시지
|
||||
3. **WeldingDetectionReq/Res** - ISO 15118-2 DC 충전 필수 메시지
|
||||
|
||||
### Phase 2: 전력 제어 메시지 (중간 우선순위)
|
||||
4. **PowerDeliveryReq/Res** - 충전 흐름 제어를 위한 필수 메시지
|
||||
|
||||
### Phase 3: 세션 관리 메시지 (중간 우선순위)
|
||||
5. **SessionSetupReq/Res** - 세션 시작
|
||||
6. **SessionStopReq/Res** - 세션 종료
|
||||
|
||||
### Phase 4: 서비스 검색 메시지 (낮은 우선순위)
|
||||
7. **ServiceDiscoveryReq/Res**
|
||||
8. **ChargeParameterDiscoveryReq/Res**
|
||||
|
||||
## 기술적 고려사항
|
||||
|
||||
### XML 패턴 인식
|
||||
- 각 메시지 타입별로 XML 태그 패턴 인식 로직 필요
|
||||
- 네임스페이스 처리 (`<ns3:CableCheckReq>` 형식)
|
||||
|
||||
### EXI 인코딩/디코딩
|
||||
- ISO1 EXI 구조체 매핑
|
||||
- 비트스트림 정확한 처리
|
||||
|
||||
### 구조체 초기화
|
||||
- 각 메시지별 `init_iso1*Type()` 함수 활용
|
||||
- `_isUsed` 플래그 올바른 설정
|
||||
|
||||
### VC2022 포팅 고려사항
|
||||
- DEBUG_PRINTF 매크로 일관성 유지
|
||||
- 기존 코드 스타일 준수
|
||||
- Windows 특화 빌드 설정
|
||||
|
||||
### dotnet 포팅 고려사항
|
||||
- C# 클래스 구조체 변환
|
||||
- 메모리 관리 차이점 고려
|
||||
- .NET Core 호환성
|
||||
80
struct_exi.txt
Normal file
80
struct_exi.txt
Normal file
@@ -0,0 +1,80 @@
|
||||
=== ISO1 EXI Document Structure Dump ===
|
||||
|
||||
V2G_Message_isUsed: 1
|
||||
|
||||
--- Header ---
|
||||
SessionID.bytesLen: 8
|
||||
SessionID.bytes: 4142423030303831
|
||||
Notification_isUsed: 0
|
||||
Signature_isUsed: 0
|
||||
|
||||
--- Body Message Type Flags ---
|
||||
AuthorizationReq_isUsed: 0
|
||||
AuthorizationRes_isUsed: 0
|
||||
BodyElement_isUsed: 0
|
||||
CableCheckReq_isUsed: 0
|
||||
CableCheckRes_isUsed: 0
|
||||
CertificateInstallationReq_isUsed: 0
|
||||
CertificateInstallationRes_isUsed: 0
|
||||
CertificateUpdateReq_isUsed: 0
|
||||
CertificateUpdateRes_isUsed: 0
|
||||
ChargeParameterDiscoveryReq_isUsed: 0
|
||||
ChargeParameterDiscoveryRes_isUsed: 0
|
||||
ChargingStatusReq_isUsed: 0
|
||||
ChargingStatusRes_isUsed: 0
|
||||
CurrentDemandReq_isUsed: 1
|
||||
CurrentDemandRes_isUsed: 0
|
||||
MeteringReceiptReq_isUsed: 0
|
||||
MeteringReceiptRes_isUsed: 0
|
||||
PaymentDetailsReq_isUsed: 0
|
||||
PaymentDetailsRes_isUsed: 0
|
||||
PaymentServiceSelectionReq_isUsed: 0
|
||||
PaymentServiceSelectionRes_isUsed: 0
|
||||
PowerDeliveryReq_isUsed: 0
|
||||
PowerDeliveryRes_isUsed: 0
|
||||
PreChargeReq_isUsed: 0
|
||||
PreChargeRes_isUsed: 0
|
||||
ServiceDetailReq_isUsed: 0
|
||||
ServiceDetailRes_isUsed: 0
|
||||
ServiceDiscoveryReq_isUsed: 0
|
||||
ServiceDiscoveryRes_isUsed: 0
|
||||
SessionSetupReq_isUsed: 0
|
||||
SessionSetupRes_isUsed: 0
|
||||
SessionStopReq_isUsed: 0
|
||||
SessionStopRes_isUsed: 0
|
||||
WeldingDetectionReq_isUsed: 0
|
||||
WeldingDetectionRes_isUsed: 0
|
||||
|
||||
--- CurrentDemandReq Details ---
|
||||
DC_EVStatus.EVReady: 1
|
||||
DC_EVStatus.EVErrorCode: 0
|
||||
DC_EVStatus.EVRESSSOC: 100
|
||||
EVTargetCurrent.Multiplier: 0
|
||||
EVTargetCurrent.Unit: 3
|
||||
EVTargetCurrent.Value: 1
|
||||
EVMaximumVoltageLimit_isUsed: 1
|
||||
EVMaximumVoltageLimit.Multiplier: 0
|
||||
EVMaximumVoltageLimit.Unit: 4
|
||||
EVMaximumVoltageLimit.Value: 471
|
||||
EVMaximumCurrentLimit_isUsed: 1
|
||||
EVMaximumCurrentLimit.Multiplier: 0
|
||||
EVMaximumCurrentLimit.Unit: 3
|
||||
EVMaximumCurrentLimit.Value: 100
|
||||
EVMaximumPowerLimit_isUsed: 1
|
||||
EVMaximumPowerLimit.Multiplier: 3
|
||||
EVMaximumPowerLimit.Unit: 5
|
||||
EVMaximumPowerLimit.Value: 50
|
||||
BulkChargingComplete_isUsed: 1
|
||||
BulkChargingComplete: 0
|
||||
ChargingComplete: 1
|
||||
RemainingTimeToFullSoC_isUsed: 1
|
||||
RemainingTimeToFullSoC.Multiplier: 0
|
||||
RemainingTimeToFullSoC.Unit: 2
|
||||
RemainingTimeToFullSoC.Value: 0
|
||||
RemainingTimeToBulkSoC_isUsed: 1
|
||||
RemainingTimeToBulkSoC.Multiplier: 0
|
||||
RemainingTimeToBulkSoC.Unit: 2
|
||||
RemainingTimeToBulkSoC.Value: 0
|
||||
EVTargetVoltage.Multiplier: 0
|
||||
EVTargetVoltage.Unit: 4
|
||||
EVTargetVoltage.Value: 460
|
||||
Reference in New Issue
Block a user