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))); |                 // 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)); |                 uint mask = (uint)(0xFF >> (EXIConstantsExact.BITS_IN_BYTE - numBits)); | ||||||
|                 // Console.Error.WriteLine($"🔬 [writeBits] mask=0x{mask:X2}"); |                 // 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)); |                 _stream.Buffer = (byte)((_stream.Buffer << numBits) | (val & mask)); | ||||||
|                 // Console.Error.WriteLine($"🔬 [writeBits] new buffer=0x{_stream.Buffer:X2}"); |                 // Console.Error.WriteLine($"🔬 [writeBits] new buffer=0x{_stream.Buffer:X2}"); | ||||||
|                  |                  | ||||||
| @@ -288,6 +292,11 @@ namespace V2GDecoderNet.EXI | |||||||
|             else |             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)) ); |                 // 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) | |                 _stream.Buffer = (byte)((_stream.Buffer << _stream.Capacity) | | ||||||
|                     (((byte)(val >> (numBits - _stream.Capacity))) & (byte)(0xFF >> (EXIConstantsExact.BITS_IN_BYTE - _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; |                 // VC2022 line 75: stream->data[(*stream->pos)++] = stream->buffer; | ||||||
|                 if (_stream.Position >= _stream.Size) |                 if (_stream.Position >= _stream.Size) | ||||||
|                     throw new InvalidOperationException("Output buffer overflow"); |                     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; |                 _stream.Data[_stream.Position++] = _stream.Buffer; | ||||||
|                  |                  | ||||||
|                 // VC2022 line 83: stream->buffer = 0; |                 // VC2022 line 83: stream->buffer = 0; | ||||||
| @@ -325,6 +336,8 @@ namespace V2GDecoderNet.EXI | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public void WriteBit(int bit) |         public void WriteBit(int bit) | ||||||
|         { |         { | ||||||
|  |             if (Position >= 28 && Position <= 35) | ||||||
|  |                 Console.Error.WriteLine($"🔍 [WriteBit] pos={Position}:{BitPosition}, bit={bit}"); | ||||||
|             writeBits(1, bit); |             writeBits(1, bit); | ||||||
|         } |         } | ||||||
|          |          | ||||||
| @@ -333,11 +346,11 @@ namespace V2GDecoderNet.EXI | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public void WriteBits(int numBits, int val) |         public void WriteBits(int numBits, int val) | ||||||
|         { |         { | ||||||
|             // if (Position >= 28 && Position <= 35) |             if (Position >= 28 && Position <= 45) | ||||||
|             //     Console.Error.WriteLine($"🔍 [WriteBits] pos={Position}, writing {numBits} bits, val={val:X}"); |                 Console.Error.WriteLine($"🔍 [WriteBits] pos={Position}, writing {numBits} bits, val={val:X}"); | ||||||
|             writeBits(numBits, val); |             writeBits(numBits, val); | ||||||
|             // if (Position >= 28 && Position <= 35) |             if (Position >= 28 && Position <= 45) | ||||||
|             //     Console.Error.WriteLine($"🔍 [WriteBits] pos after={Position}"); |                 Console.Error.WriteLine($"🔍 [WriteBits] pos after={Position}"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -348,7 +361,8 @@ namespace V2GDecoderNet.EXI | |||||||
|         { |         { | ||||||
|             if (numBits > 0) |             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); |                 writeBits(numBits, val); | ||||||
|                 // Console.Error.WriteLine($"🔬 [encodeNBit] After write pos_after={Position}, buf=0x{BufferState:X2}, cap={CapacityState}"); |                 // Console.Error.WriteLine($"🔬 [encodeNBit] After write pos_after={Position}, buf=0x{BufferState:X2}, cap={CapacityState}"); | ||||||
|             } |             } | ||||||
| @@ -357,6 +371,9 @@ namespace V2GDecoderNet.EXI | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Compatibility wrapper - keep C# naming for internal use |         /// Compatibility wrapper - keep C# naming for internal use | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  |         /// <summary> | ||||||
|  |         /// Legacy C# style alias for backward compatibility | ||||||
|  |         /// </summary> | ||||||
|         public void WriteNBitUnsignedInteger(int numBits, int val) => encodeNBitUnsignedInteger(numBits, val); |         public void WriteNBitUnsignedInteger(int numBits, int val) => encodeNBitUnsignedInteger(numBits, val); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -554,9 +571,12 @@ namespace V2GDecoderNet.EXI | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public void WriteInteger16(short val) |         public void WriteInteger16(short val) | ||||||
|         { |         { | ||||||
|  |             Console.Error.WriteLine($"🔢 [WriteInteger16] Input: {val}"); | ||||||
|  |              | ||||||
|             // Write sign bit (1 bit)   |             // Write sign bit (1 bit)   | ||||||
|             bool isNegative = val < 0; |             bool isNegative = val < 0; | ||||||
|             WriteBit(isNegative ? 1 : 0); |             WriteBit(isNegative ? 1 : 0); | ||||||
|  |             Console.Error.WriteLine($"🔢 [WriteInteger16] Sign bit: {(isNegative ? 1 : 0)} (negative: {isNegative})"); | ||||||
|              |              | ||||||
|             // Calculate unsigned magnitude |             // Calculate unsigned magnitude | ||||||
|             uint magnitude; |             uint magnitude; | ||||||
| @@ -571,6 +591,8 @@ namespace V2GDecoderNet.EXI | |||||||
|                 magnitude = (uint)val; |                 magnitude = (uint)val; | ||||||
|             } |             } | ||||||
|              |              | ||||||
|  |             Console.Error.WriteLine($"🔢 [WriteInteger16] Magnitude: {magnitude}"); | ||||||
|  |              | ||||||
|             // Write unsigned magnitude using VC2022's encodeUnsignedInteger16  |             // Write unsigned magnitude using VC2022's encodeUnsignedInteger16  | ||||||
|             encodeUnsignedInteger16((ushort)magnitude); |             encodeUnsignedInteger16((ushort)magnitude); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Text; | using System.Text; | ||||||
|  | using System.Linq; | ||||||
|  |  | ||||||
| namespace V2GDecoderNet | namespace V2GDecoderNet | ||||||
| { | { | ||||||
| @@ -20,6 +21,7 @@ namespace V2GDecoderNet | |||||||
|         private const ushort V2G_PAYLOAD_ISO2 = 0x8002;        // ISO 15118-20 payload type |         private const ushort V2G_PAYLOAD_ISO2 = 0x8002;        // ISO 15118-20 payload type | ||||||
|         private const ushort EXI_START_PATTERN = 0x8098;       // EXI document start pattern |         private const ushort EXI_START_PATTERN = 0x8098;       // EXI document start pattern | ||||||
|  |  | ||||||
|  |  | ||||||
|         static int Main(string[] args) |         static int Main(string[] args) | ||||||
|         { |         { | ||||||
|             bool xmlMode = false; |             bool xmlMode = false; | ||||||
| @@ -52,16 +54,17 @@ namespace V2GDecoderNet | |||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             {              |             {              | ||||||
|                 Console.Error.WriteLine($"Usage: {Environment.GetCommandLineArgs()[0]} [-debug] [-decode|-encode] input_file"); |                 Console.Error.WriteLine("Usage: V2GDecoderNet [-decode|-encode] input_file"); | ||||||
|                 Console.Error.WriteLine($"       {Environment.GetCommandLineArgs()[0]} [-debug] -encode          (read XML from stdin)"); |                 Console.Error.WriteLine("       V2GDecoderNet -encode          (read XML from stdin)"); | ||||||
|                 Console.Error.WriteLine($"       {Environment.GetCommandLineArgs()[0]} [-debug] -decode          (read hex string 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("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      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      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("  (default)    Analyze EXI with detailed output"); | ||||||
|  |                 Console.Error.WriteLine(""); | ||||||
|  |                 Console.Error.WriteLine("Contact: tindevil82@gmail.com"); | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|                          |                          | ||||||
| @@ -105,11 +108,22 @@ namespace V2GDecoderNet | |||||||
|                     return -1; |                     return -1; | ||||||
|                 } |                 } | ||||||
|                  |                  | ||||||
|                 // Force binary output using stream approach |                 // Check if output is redirected | ||||||
|                 using (var stdout = Console.OpenStandardOutput()) |                 bool isRedirected = Console.IsOutputRedirected; | ||||||
|  |                  | ||||||
|  |                 if (isRedirected) | ||||||
|                 { |                 { | ||||||
|                     stdout.Write(exiData, 0, exiData.Length); |                     // Binary output for redirection (file output) | ||||||
|                     stdout.Flush(); |                     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; |                 return 0; | ||||||
| @@ -158,14 +172,35 @@ namespace V2GDecoderNet | |||||||
|                 } |                 } | ||||||
|                  |                  | ||||||
|                 // Decode EXI message |                 // 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 (result.Success) | ||||||
|                 { |                 { | ||||||
|                     if (xmlMode) |                     if (xmlMode) | ||||||
|                     { |                     { | ||||||
|                         // XML decode mode - output Wireshark-style XML |                         // XML decode mode - output clean XML only | ||||||
|                         Console.WriteLine(result.XmlOutput); |                         Console.Write(result.XmlOutput); | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
| @@ -315,11 +350,22 @@ namespace V2GDecoderNet | |||||||
|                     return -1; |                     return -1; | ||||||
|                 } |                 } | ||||||
|                  |                  | ||||||
|                 // Output binary data to stdout |                 // Check if output is redirected | ||||||
|                 using (var stdout = Console.OpenStandardOutput()) |                 bool isRedirected = Console.IsOutputRedirected; | ||||||
|  |                  | ||||||
|  |                 if (isRedirected) | ||||||
|                 { |                 { | ||||||
|                     stdout.Write(exiData, 0, exiData.Length); |                     // Binary output for redirection | ||||||
|                     stdout.Flush(); |                     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; |                 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   |                 // Step 2: Encode V2G_Message choice 76 in 7-bit encoding   | ||||||
|                 // matches: if(exiDoc->V2G_Message_isUsed == 1u) encodeNBitUnsignedInteger(stream, 7, 76); |                 // 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 |                 // Step 3: Encode V2G_Message structure - Grammar states 256→257→3 | ||||||
|                 EncodeAnonType_V2G_Message(stream, message); |                 EncodeAnonType_V2G_Message(stream, message); | ||||||
| @@ -229,21 +229,21 @@ namespace V2GDecoderNet.V2G | |||||||
|                 { |                 { | ||||||
|                     case 256: // Grammar 256: Header is mandatory |                     case 256: // Grammar 256: Header is mandatory | ||||||
|                         // Console.Error.WriteLine($"🔍 [Grammar 256] Encoding Header, position: {stream.Position}"); |                         // 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); |                         EncodeMessageHeaderType(stream, message); | ||||||
|                         grammarID = 257; |                         grammarID = 257; | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
|                     case 257: // Grammar 257: Body is mandatory |                     case 257: // Grammar 257: Body is mandatory | ||||||
|                         // Console.Error.WriteLine($"🔍 [Grammar 257] Encoding Body, position: {stream.Position}"); |                         // 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); |                         EncodeBodyType(stream, message.Body); | ||||||
|                         grammarID = 3; |                         grammarID = 3; | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
|                     case 3: // Grammar 3: END_ELEMENT |                     case 3: // Grammar 3: END_ELEMENT | ||||||
|                         // Console.Error.WriteLine($"🔍 [Grammar 3] END_ELEMENT, position: {stream.Position}"); |                         // Console.Error.WriteLine($"🔍 [Grammar 3] END_ELEMENT, position: {stream.Position}"); | ||||||
|                         stream.WriteNBitUnsignedInteger(1, 0); // END_ELEMENT |                         stream.encodeNBitUnsignedInteger(1, 0); // END_ELEMENT | ||||||
|                         done = true; |                         done = true; | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
| @@ -265,10 +265,10 @@ namespace V2GDecoderNet.V2G | |||||||
| //             Console.Error.WriteLine($"🔍 [MessageHeader] Starting encoding, position: {stream.Position}"); | //             Console.Error.WriteLine($"🔍 [MessageHeader] Starting encoding, position: {stream.Position}"); | ||||||
|              |              | ||||||
|             // Grammar state 0: SessionID is mandatory |             // 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 |             // 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 |             // Convert SessionID hex string to bytes - exact match to VC2022 structure | ||||||
|             byte[] sessionIdBytes = ConvertHexStringToBytes(message.SessionID ?? "4142423030303831"); |             byte[] sessionIdBytes = ConvertHexStringToBytes(message.SessionID ?? "4142423030303831"); | ||||||
| @@ -284,10 +284,10 @@ namespace V2GDecoderNet.V2G | |||||||
|             } |             } | ||||||
| //             Console.Error.WriteLine($"🔍 [SessionID] Bytes written, position: {stream.Position}"); | //             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 |             // 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}"); | //             Console.Error.WriteLine($"🔍 [MessageHeader] Encoding completed, position: {stream.Position}"); | ||||||
|         } |         } | ||||||
| @@ -304,13 +304,13 @@ namespace V2GDecoderNet.V2G | |||||||
|             if (body.CurrentDemandReq_isUsed) |             if (body.CurrentDemandReq_isUsed) | ||||||
|             { |             { | ||||||
| //                 Console.Error.WriteLine($"🔍 [Body] Encoding CurrentDemandReq (choice 13)"); | //                 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); |                 EncodeCurrentDemandReqType(stream, body.CurrentDemandReq); | ||||||
|             } |             } | ||||||
|             else if (body.CurrentDemandRes_isUsed) |             else if (body.CurrentDemandRes_isUsed) | ||||||
|             { |             { | ||||||
| //                 Console.Error.WriteLine($"🔍 [Body] Encoding CurrentDemandRes (choice 14)"); | //                 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); |                 EncodeCurrentDemandResType(stream, body.CurrentDemandRes); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
| @@ -320,7 +320,7 @@ namespace V2GDecoderNet.V2G | |||||||
|             } |             } | ||||||
|              |              | ||||||
|             // Grammar state 3: END_ELEMENT |             // Grammar state 3: END_ELEMENT | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); |             stream.encodeNBitUnsignedInteger(1, 0); | ||||||
|              |              | ||||||
| //             Console.Error.WriteLine($"🔍 [Body] Encoding completed, position: {stream.Position}"); | //             Console.Error.WriteLine($"🔍 [Body] Encoding completed, position: {stream.Position}"); | ||||||
|         } |         } | ||||||
| @@ -343,13 +343,13 @@ namespace V2GDecoderNet.V2G | |||||||
|                 switch (grammarID) |                 switch (grammarID) | ||||||
|                 { |                 { | ||||||
|                     case 273: // DC_EVStatus is mandatory |                     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); |                         EncodeDC_EVStatusType(stream, req.DC_EVStatus); | ||||||
|                         grammarID = 274; |                         grammarID = 274; | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
|                     case 274: // EVTargetCurrent is mandatory |                     case 274: // EVTargetCurrent is mandatory | ||||||
|                         stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(EVTargetCurrent) |                         stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(EVTargetCurrent) | ||||||
|                         EncodePhysicalValueType(stream, req.EVTargetCurrent); |                         EncodePhysicalValueType(stream, req.EVTargetCurrent); | ||||||
|                         grammarID = 275; |                         grammarID = 275; | ||||||
|                         break; |                         break; | ||||||
| @@ -363,35 +363,35 @@ namespace V2GDecoderNet.V2G | |||||||
|                         if (req.EVMaximumVoltageLimit_isUsed) |                         if (req.EVMaximumVoltageLimit_isUsed) | ||||||
|                         { |                         { | ||||||
|                             Console.Error.WriteLine($"🔍 Grammar 275: choice 0 (EVMaximumVoltageLimit), 3-bit=0"); |                             Console.Error.WriteLine($"🔍 Grammar 275: choice 0 (EVMaximumVoltageLimit), 3-bit=0"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 0); |                             stream.encodeNBitUnsignedInteger(3, 0); | ||||||
|                             EncodePhysicalValueType(stream, req.EVMaximumVoltageLimit); |                             EncodePhysicalValueType(stream, req.EVMaximumVoltageLimit); | ||||||
|                             grammarID = 276; |                             grammarID = 276; | ||||||
|                         } |                         } | ||||||
|                         else if (req.EVMaximumCurrentLimit_isUsed) |                         else if (req.EVMaximumCurrentLimit_isUsed) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"🔍 Grammar 275: choice 1 (EVMaximumCurrentLimit), 3-bit=1"); | //                             Console.Error.WriteLine($"🔍 Grammar 275: choice 1 (EVMaximumCurrentLimit), 3-bit=1"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 1); |                             stream.encodeNBitUnsignedInteger(3, 1); | ||||||
|                             EncodePhysicalValueType(stream, req.EVMaximumCurrentLimit); |                             EncodePhysicalValueType(stream, req.EVMaximumCurrentLimit); | ||||||
|                             grammarID = 277; |                             grammarID = 277; | ||||||
|                         } |                         } | ||||||
|                         else if (req.EVMaximumPowerLimit_isUsed) |                         else if (req.EVMaximumPowerLimit_isUsed) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"🔍 Grammar 275: choice 2 (EVMaximumPowerLimit), 3-bit=2"); | //                             Console.Error.WriteLine($"🔍 Grammar 275: choice 2 (EVMaximumPowerLimit), 3-bit=2"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 2); |                             stream.encodeNBitUnsignedInteger(3, 2); | ||||||
|                             EncodePhysicalValueType(stream, req.EVMaximumPowerLimit); |                             EncodePhysicalValueType(stream, req.EVMaximumPowerLimit); | ||||||
|                             grammarID = 278; |                             grammarID = 278; | ||||||
|                         } |                         } | ||||||
|                         else if (req.BulkChargingComplete_isUsed) |                         else if (req.BulkChargingComplete_isUsed) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"🔍 Grammar 275: choice 3 (BulkChargingComplete), 3-bit=3"); | //                             Console.Error.WriteLine($"🔍 Grammar 275: choice 3 (BulkChargingComplete), 3-bit=3"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 3); |                             stream.encodeNBitUnsignedInteger(3, 3); | ||||||
|                             EncodeBooleanElement(stream, req.BulkChargingComplete); |                             EncodeBooleanElement(stream, req.BulkChargingComplete); | ||||||
|                             grammarID = 279; |                             grammarID = 279; | ||||||
|                         } |                         } | ||||||
|                         else // ChargingComplete is mandatory default (if( 1 == 1 )) |                         else // ChargingComplete is mandatory default (if( 1 == 1 )) | ||||||
|                         { |                         { | ||||||
|                             Console.Error.WriteLine($"🔍 Grammar 275: choice 4 (ChargingComplete), 3-bit=4"); |                             Console.Error.WriteLine($"🔍 Grammar 275: choice 4 (ChargingComplete), 3-bit=4"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 4); |                             stream.encodeNBitUnsignedInteger(3, 4); | ||||||
|                             EncodeBooleanElement(stream, req.ChargingComplete); |                             EncodeBooleanElement(stream, req.ChargingComplete); | ||||||
|                             grammarID = 280; |                             grammarID = 280; | ||||||
|                         } |                         } | ||||||
| @@ -405,28 +405,28 @@ namespace V2GDecoderNet.V2G | |||||||
|                         if (req.EVMaximumCurrentLimit_isUsed) |                         if (req.EVMaximumCurrentLimit_isUsed) | ||||||
|                         { |                         { | ||||||
|                             Console.Error.WriteLine($"🔍 Grammar 276: choice 0 (EVMaximumCurrentLimit), 3-bit=0"); |                             Console.Error.WriteLine($"🔍 Grammar 276: choice 0 (EVMaximumCurrentLimit), 3-bit=0"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 0); |                             stream.encodeNBitUnsignedInteger(3, 0); | ||||||
|                             EncodePhysicalValueType(stream, req.EVMaximumCurrentLimit); |                             EncodePhysicalValueType(stream, req.EVMaximumCurrentLimit); | ||||||
|                             grammarID = 277; |                             grammarID = 277; | ||||||
|                         } |                         } | ||||||
|                         else if (req.EVMaximumPowerLimit_isUsed) |                         else if (req.EVMaximumPowerLimit_isUsed) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"🔍 Grammar 276: choice 1 (EVMaximumPowerLimit), 3-bit=1"); | //                             Console.Error.WriteLine($"🔍 Grammar 276: choice 1 (EVMaximumPowerLimit), 3-bit=1"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 1); |                             stream.encodeNBitUnsignedInteger(3, 1); | ||||||
|                             EncodePhysicalValueType(stream, req.EVMaximumPowerLimit); |                             EncodePhysicalValueType(stream, req.EVMaximumPowerLimit); | ||||||
|                             grammarID = 278; |                             grammarID = 278; | ||||||
|                         } |                         } | ||||||
|                         else if (req.BulkChargingComplete_isUsed) |                         else if (req.BulkChargingComplete_isUsed) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"🔍 Grammar 276: choice 2 (BulkChargingComplete), 3-bit=2"); | //                             Console.Error.WriteLine($"🔍 Grammar 276: choice 2 (BulkChargingComplete), 3-bit=2"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 2); |                             stream.encodeNBitUnsignedInteger(3, 2); | ||||||
|                             EncodeBooleanElement(stream, req.BulkChargingComplete); |                             EncodeBooleanElement(stream, req.BulkChargingComplete); | ||||||
|                             grammarID = 279; |                             grammarID = 279; | ||||||
|                         } |                         } | ||||||
|                         else // ChargingComplete (if( 1 == 1 )) |                         else // ChargingComplete (if( 1 == 1 )) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"🔍 Grammar 276: choice 3 (ChargingComplete), 3-bit=3"); | //                             Console.Error.WriteLine($"🔍 Grammar 276: choice 3 (ChargingComplete), 3-bit=3"); | ||||||
|                             stream.WriteNBitUnsignedInteger(3, 3); |                             stream.encodeNBitUnsignedInteger(3, 3); | ||||||
|                             EncodeBooleanElement(stream, req.ChargingComplete); |                             EncodeBooleanElement(stream, req.ChargingComplete); | ||||||
|                             grammarID = 280; |                             grammarID = 280; | ||||||
|                         } |                         } | ||||||
| @@ -439,21 +439,21 @@ namespace V2GDecoderNet.V2G | |||||||
|                         if (req.EVMaximumPowerLimit_isUsed) |                         if (req.EVMaximumPowerLimit_isUsed) | ||||||
|                         { |                         { | ||||||
|                             Console.Error.WriteLine($"🔍 Grammar 277: choice 0 (EVMaximumPowerLimit), 2-bit=0"); |                             Console.Error.WriteLine($"🔍 Grammar 277: choice 0 (EVMaximumPowerLimit), 2-bit=0"); | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 0); |                             stream.encodeNBitUnsignedInteger(2, 0); | ||||||
|                             EncodePhysicalValueType(stream, req.EVMaximumPowerLimit); |                             EncodePhysicalValueType(stream, req.EVMaximumPowerLimit); | ||||||
|                             grammarID = 278; |                             grammarID = 278; | ||||||
|                         } |                         } | ||||||
|                         else if (req.BulkChargingComplete_isUsed) |                         else if (req.BulkChargingComplete_isUsed) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"🔍 Grammar 277: choice 1 (BulkChargingComplete), 2-bit=1"); | //                             Console.Error.WriteLine($"🔍 Grammar 277: choice 1 (BulkChargingComplete), 2-bit=1"); | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 1); |                             stream.encodeNBitUnsignedInteger(2, 1); | ||||||
|                             EncodeBooleanElement(stream, req.BulkChargingComplete); |                             EncodeBooleanElement(stream, req.BulkChargingComplete); | ||||||
|                             grammarID = 279; |                             grammarID = 279; | ||||||
|                         } |                         } | ||||||
|                         else // ChargingComplete (if( 1 == 1 )) |                         else // ChargingComplete (if( 1 == 1 )) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"🔍 Grammar 277: choice 2 (ChargingComplete), 2-bit=2"); | //                             Console.Error.WriteLine($"🔍 Grammar 277: choice 2 (ChargingComplete), 2-bit=2"); | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 2); |                             stream.encodeNBitUnsignedInteger(2, 2); | ||||||
|                             EncodeBooleanElement(stream, req.ChargingComplete); |                             EncodeBooleanElement(stream, req.ChargingComplete); | ||||||
|                             grammarID = 280; |                             grammarID = 280; | ||||||
|                         } |                         } | ||||||
| @@ -464,85 +464,107 @@ namespace V2GDecoderNet.V2G | |||||||
|                          |                          | ||||||
|                         if (req.BulkChargingComplete_isUsed) |                         if (req.BulkChargingComplete_isUsed) | ||||||
|                         { |                         { | ||||||
| //                             Console.Error.WriteLine($"📍 Grammar 278: choice 0 (BulkChargingComplete), 2-bit=0"); |                             Console.Error.WriteLine($"📍 Grammar 278: choice 0 (BulkChargingComplete), 2-bit=0"); | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 0); |                             stream.encodeNBitUnsignedInteger(2, 0); | ||||||
|                             EncodeBooleanElement(stream, req.BulkChargingComplete); |                             EncodeBooleanElement(stream, req.BulkChargingComplete); | ||||||
|                             grammarID = 279; |                             grammarID = 279; | ||||||
|                         } |                         } | ||||||
|                         else // ChargingComplete (if( 1 == 1 )) |                         else // ChargingComplete (if( 1 == 1 )) | ||||||
|                         { |                         { | ||||||
|                             Console.Error.WriteLine($"📍 Grammar 278: choice 1 (ChargingComplete), 2-bit=1"); |                             Console.Error.WriteLine($"📍 Grammar 278: choice 1 (ChargingComplete), 2-bit=1"); | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 1); |                             stream.encodeNBitUnsignedInteger(2, 1); | ||||||
|                             EncodeBooleanElement(stream, req.ChargingComplete); |                             EncodeBooleanElement(stream, req.ChargingComplete); | ||||||
|                             grammarID = 280; |                             grammarID = 280; | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
|                     case 279: // After BulkChargingComplete - skip to optional elements |                     case 279: // After BulkChargingComplete - VC2022: 1-bit choice for ChargingComplete | ||||||
|                         if (req.RemainingTimeToFullSoC_isUsed) |                         Console.Error.WriteLine($"🔍 Grammar 279: ChargingComplete always required (1==1)"); | ||||||
|                         { |                          | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 0); |                         // VC2022 Grammar 279: 1-bit choice, not 2-bit! | ||||||
|                             EncodePhysicalValueType(stream, req.RemainingTimeToFullSoC); |                         Console.Error.WriteLine($"📍 Grammar 279: choice 0 (ChargingComplete={req.ChargingComplete}), 1-bit=0"); | ||||||
|                             grammarID = 281; |                         stream.encodeNBitUnsignedInteger(1, 0); | ||||||
|                         } |                         EncodeBooleanElement(stream, req.ChargingComplete); | ||||||
|                         else if (req.RemainingTimeToBulkSoC_isUsed) |                         grammarID = 280; | ||||||
|                         { |  | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 1); |  | ||||||
|                             EncodePhysicalValueType(stream, req.RemainingTimeToBulkSoC); |  | ||||||
|                             grammarID = 282; |  | ||||||
|                         } |  | ||||||
|                         else |  | ||||||
|                         { |  | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 2); |  | ||||||
|                             EncodePhysicalValueType(stream, req.EVTargetVoltage); // Mandatory |  | ||||||
|                             grammarID = 3; // END |  | ||||||
|                         } |  | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
|                     case 280: // After ChargingComplete - 2-bit choice |                     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) |                         if (req.RemainingTimeToFullSoC_isUsed) | ||||||
|                         { |                         { | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 0); |                             stream.encodeNBitUnsignedInteger(2, 0); | ||||||
|                             EncodePhysicalValueType(stream, req.RemainingTimeToFullSoC); |                             EncodePhysicalValueType(stream, req.RemainingTimeToFullSoC); | ||||||
|                             grammarID = 281; |                             grammarID = 281; | ||||||
|                         } |                         } | ||||||
|                         else if (req.RemainingTimeToBulkSoC_isUsed) |                         else if (req.RemainingTimeToBulkSoC_isUsed) | ||||||
|                         { |                         { | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 1); |                             stream.encodeNBitUnsignedInteger(2, 1); | ||||||
|                             EncodePhysicalValueType(stream, req.RemainingTimeToBulkSoC); |                             EncodePhysicalValueType(stream, req.RemainingTimeToBulkSoC); | ||||||
|                             grammarID = 282; |                             grammarID = 282; | ||||||
|                         } |                         } | ||||||
|                         else |                         else | ||||||
|                         { |                         { | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 2); |                             // Skip to Grammar 283 (EVTargetVoltage processing) | ||||||
|                             EncodePhysicalValueType(stream, req.EVTargetVoltage); // Mandatory |                             stream.encodeNBitUnsignedInteger(2, 2); | ||||||
|                             grammarID = 3; // END |                             grammarID = 283; | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
|                     case 281: // After RemainingTimeToFullSoC - 2-bit choice |                     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) |                         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); |                             EncodePhysicalValueType(stream, req.RemainingTimeToBulkSoC); | ||||||
|                             grammarID = 282; |                             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 |                         else | ||||||
|                         { |                         { | ||||||
|                             stream.WriteNBitUnsignedInteger(2, 1); |                             Console.Error.WriteLine("📍 Grammar 281: choice 2 (END_ELEMENT), 2-bit=2"); | ||||||
|                             EncodePhysicalValueType(stream, req.EVTargetVoltage); // Mandatory |                             stream.encodeNBitUnsignedInteger(2, 2); // END_ELEMENT choice | ||||||
|                             grammarID = 3; // END |                             grammarID = 3; // END | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
|                     case 282: // After RemainingTimeToBulkSoC - 1-bit choice |                     case 282: // After RemainingTimeToBulkSoC - 1-bit choice | ||||||
|                         stream.WriteNBitUnsignedInteger(1, 0); |                         Console.Error.WriteLine($"🔍 Grammar 282: EVTargetVoltage != null = {req.EVTargetVoltage != null}"); | ||||||
|                         EncodePhysicalValueType(stream, req.EVTargetVoltage); // Mandatory |                         // 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 |                         grammarID = 3; // END | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
|                     case 3: // END_ELEMENT |                     case 3: // END_ELEMENT | ||||||
|                         stream.WriteNBitUnsignedInteger(1, 0); |                         stream.encodeNBitUnsignedInteger(1, 0); | ||||||
|                         done = true; |                         done = true; | ||||||
|                         break; |                         break; | ||||||
|                          |                          | ||||||
| @@ -563,13 +585,13 @@ namespace V2GDecoderNet.V2G | |||||||
| //             Console.Error.WriteLine($"🔍 [CurrentDemandRes] Starting encoding, position: {stream.Position}"); | //             Console.Error.WriteLine($"🔍 [CurrentDemandRes] Starting encoding, position: {stream.Position}"); | ||||||
|              |              | ||||||
|             // Grammar 317: ResponseCode (mandatory) |             // Grammar 317: ResponseCode (mandatory) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(ResponseCode) |             stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(ResponseCode) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION] |             stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION] | ||||||
|             stream.WriteNBitUnsignedInteger(5, (int)res.ResponseCode); // 5-bit enumeration |             stream.encodeNBitUnsignedInteger(5, (int)res.ResponseCode); // 5-bit enumeration | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // valid EE |             stream.encodeNBitUnsignedInteger(1, 0); // valid EE | ||||||
|              |              | ||||||
|             // Simple implementation - skip complex grammar for now |             // 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}"); | //             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}"); | //             Console.Error.WriteLine($"🔍 [DC_EVStatus] Starting encoding, position: {stream.Position}"); | ||||||
|              |              | ||||||
|             // Grammar 314: EVReady (mandatory boolean) |             // Grammar 314: EVReady (mandatory boolean) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(EVReady) |             stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(EVReady) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[BOOLEAN] |             stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[BOOLEAN] | ||||||
|             stream.WriteBit(status.EVReady ? 1 : 0); // Boolean bit |             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) |             // Grammar 315: EVErrorCode (mandatory enumeration) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(EVErrorCode) |             stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(EVErrorCode) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION] |             stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION] | ||||||
|             stream.WriteNBitUnsignedInteger(4, status.EVErrorCode); // 4-bit enumeration |             stream.encodeNBitUnsignedInteger(4, status.EVErrorCode); // 4-bit enumeration | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // valid EE |             stream.encodeNBitUnsignedInteger(1, 0); // valid EE | ||||||
|              |              | ||||||
|             // Grammar 316: EVRESSSOC (mandatory 7-bit unsigned integer) |             // Grammar 316: EVRESSSOC (mandatory 7-bit unsigned integer) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT(EVRESSSOC) |             stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT(EVRESSSOC) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[NBIT_UNSIGNED_INTEGER] |             stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[NBIT_UNSIGNED_INTEGER] | ||||||
|             stream.WriteNBitUnsignedInteger(7, status.EVRESSSOC); // 7-bit unsigned (0-100) |             stream.encodeNBitUnsignedInteger(7, status.EVRESSSOC); // 7-bit unsigned (0-100) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // valid EE |             stream.encodeNBitUnsignedInteger(1, 0); // valid EE | ||||||
|              |              | ||||||
|             // Grammar 3: END_ELEMENT |             // Grammar 3: END_ELEMENT | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); |             stream.encodeNBitUnsignedInteger(1, 0); | ||||||
|              |              | ||||||
| //             Console.Error.WriteLine($"🔍 [DC_EVStatus] Encoding completed, position: {stream.Position}"); | //             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) |         private static void EncodePhysicalValueType(BitOutputStreamExact stream, PhysicalValueType value) | ||||||
|         { |         { | ||||||
|             int posBefore = stream.Position; |             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) |             // Grammar 117: START_ELEMENT(Multiplier) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT |             stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[NBIT_UNSIGNED_INTEGER] |             stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[NBIT_UNSIGNED_INTEGER] | ||||||
|             stream.WriteNBitUnsignedInteger(3, (int)(value.Multiplier + 3)); // 3-bit unsigned + 3 offset |             stream.encodeNBitUnsignedInteger(3, (int)(value.Multiplier + 3)); // 3-bit unsigned + 3 offset | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // valid EE |             stream.encodeNBitUnsignedInteger(1, 0); // valid EE | ||||||
|              |              | ||||||
|             // Grammar 118: START_ELEMENT(Unit) |             // Grammar 118: START_ELEMENT(Unit) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT |             stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION] |             stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[ENUMERATION] | ||||||
|             stream.WriteNBitUnsignedInteger(3, (int)value.Unit); // 3-bit enumeration |             stream.encodeNBitUnsignedInteger(3, (int)value.Unit); // 3-bit enumeration | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // valid EE |             stream.encodeNBitUnsignedInteger(1, 0); // valid EE | ||||||
|              |              | ||||||
|             // Grammar 119: START_ELEMENT(Value) |             // Grammar 119: START_ELEMENT(Value) | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // START_ELEMENT |             stream.encodeNBitUnsignedInteger(1, 0); // START_ELEMENT | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[INTEGER] |             stream.encodeNBitUnsignedInteger(1, 0); // CHARACTERS[INTEGER] | ||||||
|             stream.WriteInteger16((short)value.Value); // VC2022 encodeInteger16 |             stream.WriteInteger16((short)value.Value); // VC2022 encodeInteger16 | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // valid EE |             stream.encodeNBitUnsignedInteger(1, 0); // valid EE | ||||||
|              |              | ||||||
|             // Grammar 3: END_ELEMENT |             // Grammar 3: END_ELEMENT | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // END_ELEMENT |             stream.encodeNBitUnsignedInteger(1, 0); // END_ELEMENT | ||||||
|              |              | ||||||
|             int posAfter = stream.Position; |             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}"); | //             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> |         /// </summary> | ||||||
|         private static void EncodeBooleanElement(BitOutputStreamExact stream, bool value) |         private static void EncodeBooleanElement(BitOutputStreamExact stream, bool value) | ||||||
|         { |         { | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // CHARACTERS[BOOLEAN] |             Console.Error.WriteLine($"🔍 [EncodeBooleanElement] pos={stream.Position}:{stream.BitPosition}, value={value}"); | ||||||
|             stream.WriteBit(value ? 1 : 0); // Boolean bit |              | ||||||
|             stream.WriteNBitUnsignedInteger(1, 0); // valid EE |             // 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> |         /// <summary> | ||||||
|   | |||||||
| @@ -589,8 +589,8 @@ namespace V2GDecoderNet | |||||||
|             if (bulkChargingComplete != null) |             if (bulkChargingComplete != null) | ||||||
|             { |             { | ||||||
|                 req.BulkChargingComplete = bool.Parse(bulkChargingComplete.Value); |                 req.BulkChargingComplete = bool.Parse(bulkChargingComplete.Value); | ||||||
|                 // VC2022 behavior: ignore BulkChargingComplete element when value is false, keep _isUsed = false |                 // XML에서 요소가 명시적으로 포함되면 값과 관계없이 _isUsed = true | ||||||
|                 req.BulkChargingComplete_isUsed = req.BulkChargingComplete; // Only set to true if value is true |                 req.BulkChargingComplete_isUsed = true; // Element exists in XML | ||||||
|             } |             } | ||||||
|              |              | ||||||
|             var chargingComplete = reqElement.Element(ns3 + "ChargingComplete"); |             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); |     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 | // 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[]) { | int main(int argc, char *argv[]) { | ||||||
|     printf("DEBUG: argc=%d\n", argc); |     DEBUG_PRINTF(("DEBUG: argc=%d\n", argc)); | ||||||
|     int xml_mode = 0; |     int xml_mode = 0; | ||||||
|     int encode_mode = 0; |     int encode_mode = 0; | ||||||
|     char *filename = NULL; |     char *filename = NULL; | ||||||
| @@ -1179,16 +1179,17 @@ int main(int argc, char *argv[]) { | |||||||
|         encode_mode = 1; |         encode_mode = 1; | ||||||
|         filename = argv[arg_index + 1]; |         filename = argv[arg_index + 1]; | ||||||
|     } else { |     } else { | ||||||
|         printf("Usage: %s [-debug] [-decode|-encode] input_file\\n", argv[0]); |         printf("Usage: V2GDecoder [-debug] [-decode|-encode] input_file\\n"); | ||||||
|         printf("       %s [-debug] -encode          (read XML from stdin)\\n", argv[0]); |         printf("       V2GDecoder [-debug] -encode          (read XML from stdin)\\n"); | ||||||
|         printf("       %s [-debug] -decode          (read hex string from stdin)\\n", argv[0]); |         printf("       V2GDecoder [-debug] -decode          (read hex string from stdin)\\n"); | ||||||
|         printf("Enhanced EXI viewer with XML conversion capabilities\\n"); |         printf("Enhanced EXI viewer with XML conversion capabilities\\n"); | ||||||
|         printf("  -debug       Enable detailed bit-level encoding/decoding output\\n"); |         printf("  -debug       Enable detailed bit-level encoding/decoding output\\n"); | ||||||
|         printf("  -decode      Convert EXI to Wireshark-style XML format\\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      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("  (default)    Analyze EXI with detailed output\\n"); | ||||||
|  |         printf("\\nContact: tindevil82@gmail.com\\n"); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|      |      | ||||||
| @@ -1208,7 +1209,7 @@ int main(int argc, char *argv[]) { | |||||||
|      |      | ||||||
|     // Handle encode mode (XML to EXI) |     // Handle encode mode (XML to EXI) | ||||||
|     if (encode_mode) { |     if (encode_mode) { | ||||||
|         fprintf(stderr, "DEBUG: Entering encode mode\n"); |         DEBUG_PRINTF(("DEBUG: Entering encode mode\n")); | ||||||
|         FILE* xml_file; |         FILE* xml_file; | ||||||
|         char* xml_content; |         char* xml_content; | ||||||
|         long xml_size; |         long xml_size; | ||||||
| @@ -1266,9 +1267,9 @@ int main(int argc, char *argv[]) { | |||||||
|         } |         } | ||||||
|          |          | ||||||
|         // Parse XML to ISO1 document structure |         // 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); |         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) { |         if (parse_result != 0) { | ||||||
|             printf("Error parsing XML file - no supported message type found\\n"); |             printf("Error parsing XML file - no supported message type found\\n"); | ||||||
|             free(xml_content); |             free(xml_content); | ||||||
| @@ -1284,17 +1285,17 @@ int main(int argc, char *argv[]) { | |||||||
|         // Debug output disabled for clean hex-only output |         // Debug output disabled for clean hex-only output | ||||||
|          |          | ||||||
|         if (iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed) { |         if (iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed) { | ||||||
|             fprintf(stderr, "EVReady: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false"); |             DEBUG_PRINTF(("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); |             DEBUG_PRINTF(("EVErrorCode: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode)); | ||||||
|             fprintf(stderr, "EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC); |             DEBUG_PRINTF(("EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC)); | ||||||
|             fprintf(stderr, "EVTargetCurrent: M=%d, U=%d, V=%d\\n",  |             DEBUG_PRINTF(("EVTargetCurrent: M=%d, U=%d, V=%d\\n",  | ||||||
|                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier, |                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier, | ||||||
|                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit, |                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit, | ||||||
|                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value); |                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value)); | ||||||
|             fprintf(stderr, "EVTargetVoltage: M=%d, U=%d, V=%d\\n",  |             DEBUG_PRINTF(("EVTargetVoltage: M=%d, U=%d, V=%d\\n",  | ||||||
|                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier, |                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier, | ||||||
|                    iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit, |                    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; |         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")); | ||||||
|         dump_iso1_document_to_file(&iso1Doc, "temp/struct_xml.txt"); |         if (EXI_DEBUG_MODE) { | ||||||
|         fprintf(stderr, "DEBUG: Structure dump completed\n"); |             dump_iso1_document_to_file(&iso1Doc, "temp/struct_xml.txt"); | ||||||
|  |         } | ||||||
|  |         DEBUG_PRINTF(("DEBUG: Structure dump completed\n")); | ||||||
|          |          | ||||||
|         errn = encode_iso1ExiDocument(&stream, &iso1Doc); |         errn = encode_iso1ExiDocument(&stream, &iso1Doc); | ||||||
|          |          | ||||||
| @@ -1422,31 +1425,31 @@ int main(int argc, char *argv[]) { | |||||||
|             print_iso1_message(&iso1Doc); |             print_iso1_message(&iso1Doc); | ||||||
|              |              | ||||||
|             // Compare with expected structure |             // Compare with expected structure | ||||||
|             printf("\\n=== Original EXI Structure Debug ===\\n"); |             DEBUG_PRINTF(("\\n=== Original EXI Structure Debug ===\\n")); | ||||||
|             printf("V2G_Message_isUsed: %s\\n", iso1Doc.V2G_Message_isUsed ? "true" : "false"); |             DEBUG_PRINTF(("V2G_Message_isUsed: %s\\n", iso1Doc.V2G_Message_isUsed ? "true" : "false")); | ||||||
|             printf("SessionID length: %d\\n", iso1Doc.V2G_Message.Header.SessionID.bytesLen); |             DEBUG_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(("CurrentDemandReq_isUsed: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed ? "true" : "false")); | ||||||
|              |              | ||||||
|             if (iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed) { |             if (iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed) { | ||||||
|                 printf("EVReady: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false"); |                 DEBUG_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); |                 DEBUG_PRINTF(("EVErrorCode: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode)); | ||||||
|                 printf("EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC); |                 DEBUG_PRINTF(("EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC)); | ||||||
|                 printf("EVTargetCurrent: M=%d, U=%d, V=%d\\n",  |                 DEBUG_PRINTF(("EVTargetCurrent: M=%d, U=%d, V=%d\\n",  | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier, |                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier, | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit, |                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit, | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value); |                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value)); | ||||||
|                 printf("EVMaximumVoltageLimit_isUsed: %s\\n",  |                 DEBUG_PRINTF(("EVMaximumVoltageLimit_isUsed: %s\\n",  | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed ? "true" : "false"); |                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed ? "true" : "false")); | ||||||
|                 printf("EVMaximumCurrentLimit_isUsed: %s\\n",  |                 DEBUG_PRINTF(("EVMaximumCurrentLimit_isUsed: %s\\n",  | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed ? "true" : "false"); |                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed ? "true" : "false")); | ||||||
|                 printf("EVMaximumPowerLimit_isUsed: %s\\n",  |                 DEBUG_PRINTF(("EVMaximumPowerLimit_isUsed: %s\\n",  | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed ? "true" : "false"); |                        iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed ? "true" : "false")); | ||||||
|                 printf("BulkChargingComplete_isUsed: %s\\n",  |                 DEBUG_PRINTF(("BulkChargingComplete_isUsed: %s\\n",  | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed ? "true" : "false"); |                        iso1Doc.V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed ? "true" : "false")); | ||||||
|                 printf("RemainingTimeToFullSoC_isUsed: %s\\n",  |                 DEBUG_PRINTF(("RemainingTimeToFullSoC_isUsed: %s\\n",  | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed ? "true" : "false"); |                        iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed ? "true" : "false")); | ||||||
|                 printf("RemainingTimeToBulkSoC_isUsed: %s\\n",  |                 DEBUG_PRINTF(("RemainingTimeToBulkSoC_isUsed: %s\\n",  | ||||||
|                        iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed ? "true" : "false"); |                        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