fix: Resolve EXI encoding issues and enhance V2GDecoder functionality
- Fix critical EXI encoding error -109 (EXI_ERROR_UNKOWN_EVENT) by adding proper structure initialization * Added init_iso1BodyType() call before setting message type flags in XML parsing * Prevents garbage values in unused message type flags that caused wrong grammar paths - Rename enhanced_exi_viewer to V2GDecoder for consistency * Updated build.bat to build V2GDecoder instead of enhanced_exi_viewer * Maintains all existing functionality with improved reliability - Add comprehensive structure debugging capabilities * Created structure dump functions to output complete document state * Added struct_exi.txt and struct_xml.txt for comparing parsed vs original structures - Enhance output formatting for encoding operations * Clean hex-only output for encoding mode (similar to XML decode mode) * Removed debug clutter for production use while preserving debugging code - Add test infrastructure with minimal_test.xml for focused testing * Validates CurrentDemandReq message encoding with minimal required fields - Improve encoder debugging with position tracking in iso1EXIDatatypesEncoder.c * Added debug points to track exact failure locations during encoding 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -468,9 +468,23 @@ int parse_xml_to_iso1(const char* xml_content, struct iso1EXIDocument* doc) {
|
|||||||
|
|
||||||
// Check for CurrentDemandReq
|
// Check for CurrentDemandReq
|
||||||
if (strstr(xml_content, "<CurrentDemandReq>") || strstr(xml_content, "<ns3:CurrentDemandReq>")) {
|
if (strstr(xml_content, "<CurrentDemandReq>") || strstr(xml_content, "<ns3:CurrentDemandReq>")) {
|
||||||
|
// Body 구조체 초기화 (모든 메시지 타입 플래그를 0으로 설정)
|
||||||
|
init_iso1BodyType(&doc->V2G_Message.Body);
|
||||||
|
|
||||||
|
// 오직 CurrentDemandReq만 활성화
|
||||||
doc->V2G_Message.Body.CurrentDemandReq_isUsed = 1;
|
doc->V2G_Message.Body.CurrentDemandReq_isUsed = 1;
|
||||||
|
|
||||||
|
// Initialize CurrentDemandReq structure completely
|
||||||
init_iso1CurrentDemandReqType(&doc->V2G_Message.Body.CurrentDemandReq);
|
init_iso1CurrentDemandReqType(&doc->V2G_Message.Body.CurrentDemandReq);
|
||||||
|
|
||||||
|
// Set all optional fields to NOT USED by default
|
||||||
|
doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed = 0;
|
||||||
|
doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed = 0;
|
||||||
|
doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed = 0;
|
||||||
|
doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed = 0;
|
||||||
|
doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed = 0;
|
||||||
|
doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed = 0;
|
||||||
|
|
||||||
// Parse DC_EVStatus
|
// Parse DC_EVStatus
|
||||||
char* ev_ready = find_tag_content(xml_content, "EVReady");
|
char* ev_ready = find_tag_content(xml_content, "EVReady");
|
||||||
if (ev_ready) {
|
if (ev_ready) {
|
||||||
@@ -588,6 +602,10 @@ int parse_xml_to_iso1(const char* xml_content, struct iso1EXIDocument* doc) {
|
|||||||
|
|
||||||
// Check for CurrentDemandRes
|
// Check for CurrentDemandRes
|
||||||
if (strstr(xml_content, "<CurrentDemandRes>") || strstr(xml_content, "<ns3:CurrentDemandRes>")) {
|
if (strstr(xml_content, "<CurrentDemandRes>") || strstr(xml_content, "<ns3:CurrentDemandRes>")) {
|
||||||
|
// Body 구조체 초기화 (모든 메시지 타입 플래그를 0으로 설정)
|
||||||
|
init_iso1BodyType(&doc->V2G_Message.Body);
|
||||||
|
|
||||||
|
// 오직 CurrentDemandRes만 활성화
|
||||||
doc->V2G_Message.Body.CurrentDemandRes_isUsed = 1;
|
doc->V2G_Message.Body.CurrentDemandRes_isUsed = 1;
|
||||||
init_iso1CurrentDemandResType(&doc->V2G_Message.Body.CurrentDemandRes);
|
init_iso1CurrentDemandResType(&doc->V2G_Message.Body.CurrentDemandRes);
|
||||||
|
|
||||||
@@ -669,6 +687,138 @@ int parse_xml_to_iso1(const char* xml_content, struct iso1EXIDocument* doc) {
|
|||||||
return -1; // Unsupported message type
|
return -1; // Unsupported message type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 구조체 전체 내용을 텍스트 파일로 덤프하는 함수
|
||||||
|
void dump_iso1_document_to_file(const struct iso1EXIDocument* doc, const char* filename) {
|
||||||
|
FILE* fp = fopen(filename, "w");
|
||||||
|
if (!fp) {
|
||||||
|
printf("Error: Cannot create file %s\n", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "=== ISO1 EXI Document Structure Dump ===\n\n");
|
||||||
|
|
||||||
|
// Document level
|
||||||
|
fprintf(fp, "V2G_Message_isUsed: %u\n", doc->V2G_Message_isUsed);
|
||||||
|
|
||||||
|
if (doc->V2G_Message_isUsed) {
|
||||||
|
// Header
|
||||||
|
fprintf(fp, "\n--- Header ---\n");
|
||||||
|
fprintf(fp, "SessionID.bytesLen: %u\n", doc->V2G_Message.Header.SessionID.bytesLen);
|
||||||
|
fprintf(fp, "SessionID.bytes: ");
|
||||||
|
for (int i = 0; i < doc->V2G_Message.Header.SessionID.bytesLen; i++) {
|
||||||
|
fprintf(fp, "%02X", doc->V2G_Message.Header.SessionID.bytes[i]);
|
||||||
|
}
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
fprintf(fp, "Notification_isUsed: %u\n", doc->V2G_Message.Header.Notification_isUsed);
|
||||||
|
fprintf(fp, "Signature_isUsed: %u\n", doc->V2G_Message.Header.Signature_isUsed);
|
||||||
|
|
||||||
|
// Body - All message type flags
|
||||||
|
fprintf(fp, "\n--- Body Message Type Flags ---\n");
|
||||||
|
fprintf(fp, "AuthorizationReq_isUsed: %u\n", doc->V2G_Message.Body.AuthorizationReq_isUsed);
|
||||||
|
fprintf(fp, "AuthorizationRes_isUsed: %u\n", doc->V2G_Message.Body.AuthorizationRes_isUsed);
|
||||||
|
fprintf(fp, "BodyElement_isUsed: %u\n", doc->V2G_Message.Body.BodyElement_isUsed);
|
||||||
|
fprintf(fp, "CableCheckReq_isUsed: %u\n", doc->V2G_Message.Body.CableCheckReq_isUsed);
|
||||||
|
fprintf(fp, "CableCheckRes_isUsed: %u\n", doc->V2G_Message.Body.CableCheckRes_isUsed);
|
||||||
|
fprintf(fp, "CertificateInstallationReq_isUsed: %u\n", doc->V2G_Message.Body.CertificateInstallationReq_isUsed);
|
||||||
|
fprintf(fp, "CertificateInstallationRes_isUsed: %u\n", doc->V2G_Message.Body.CertificateInstallationRes_isUsed);
|
||||||
|
fprintf(fp, "CertificateUpdateReq_isUsed: %u\n", doc->V2G_Message.Body.CertificateUpdateReq_isUsed);
|
||||||
|
fprintf(fp, "CertificateUpdateRes_isUsed: %u\n", doc->V2G_Message.Body.CertificateUpdateRes_isUsed);
|
||||||
|
fprintf(fp, "ChargeParameterDiscoveryReq_isUsed: %u\n", doc->V2G_Message.Body.ChargeParameterDiscoveryReq_isUsed);
|
||||||
|
fprintf(fp, "ChargeParameterDiscoveryRes_isUsed: %u\n", doc->V2G_Message.Body.ChargeParameterDiscoveryRes_isUsed);
|
||||||
|
fprintf(fp, "ChargingStatusReq_isUsed: %u\n", doc->V2G_Message.Body.ChargingStatusReq_isUsed);
|
||||||
|
fprintf(fp, "ChargingStatusRes_isUsed: %u\n", doc->V2G_Message.Body.ChargingStatusRes_isUsed);
|
||||||
|
fprintf(fp, "CurrentDemandReq_isUsed: %u\n", doc->V2G_Message.Body.CurrentDemandReq_isUsed);
|
||||||
|
fprintf(fp, "CurrentDemandRes_isUsed: %u\n", doc->V2G_Message.Body.CurrentDemandRes_isUsed);
|
||||||
|
fprintf(fp, "MeteringReceiptReq_isUsed: %u\n", doc->V2G_Message.Body.MeteringReceiptReq_isUsed);
|
||||||
|
fprintf(fp, "MeteringReceiptRes_isUsed: %u\n", doc->V2G_Message.Body.MeteringReceiptRes_isUsed);
|
||||||
|
fprintf(fp, "PaymentDetailsReq_isUsed: %u\n", doc->V2G_Message.Body.PaymentDetailsReq_isUsed);
|
||||||
|
fprintf(fp, "PaymentDetailsRes_isUsed: %u\n", doc->V2G_Message.Body.PaymentDetailsRes_isUsed);
|
||||||
|
fprintf(fp, "PaymentServiceSelectionReq_isUsed: %u\n", doc->V2G_Message.Body.PaymentServiceSelectionReq_isUsed);
|
||||||
|
fprintf(fp, "PaymentServiceSelectionRes_isUsed: %u\n", doc->V2G_Message.Body.PaymentServiceSelectionRes_isUsed);
|
||||||
|
fprintf(fp, "PowerDeliveryReq_isUsed: %u\n", doc->V2G_Message.Body.PowerDeliveryReq_isUsed);
|
||||||
|
fprintf(fp, "PowerDeliveryRes_isUsed: %u\n", doc->V2G_Message.Body.PowerDeliveryRes_isUsed);
|
||||||
|
fprintf(fp, "PreChargeReq_isUsed: %u\n", doc->V2G_Message.Body.PreChargeReq_isUsed);
|
||||||
|
fprintf(fp, "PreChargeRes_isUsed: %u\n", doc->V2G_Message.Body.PreChargeRes_isUsed);
|
||||||
|
fprintf(fp, "ServiceDetailReq_isUsed: %u\n", doc->V2G_Message.Body.ServiceDetailReq_isUsed);
|
||||||
|
fprintf(fp, "ServiceDetailRes_isUsed: %u\n", doc->V2G_Message.Body.ServiceDetailRes_isUsed);
|
||||||
|
fprintf(fp, "ServiceDiscoveryReq_isUsed: %u\n", doc->V2G_Message.Body.ServiceDiscoveryReq_isUsed);
|
||||||
|
fprintf(fp, "ServiceDiscoveryRes_isUsed: %u\n", doc->V2G_Message.Body.ServiceDiscoveryRes_isUsed);
|
||||||
|
fprintf(fp, "SessionSetupReq_isUsed: %u\n", doc->V2G_Message.Body.SessionSetupReq_isUsed);
|
||||||
|
fprintf(fp, "SessionSetupRes_isUsed: %u\n", doc->V2G_Message.Body.SessionSetupRes_isUsed);
|
||||||
|
fprintf(fp, "SessionStopReq_isUsed: %u\n", doc->V2G_Message.Body.SessionStopReq_isUsed);
|
||||||
|
fprintf(fp, "SessionStopRes_isUsed: %u\n", doc->V2G_Message.Body.SessionStopRes_isUsed);
|
||||||
|
fprintf(fp, "WeldingDetectionReq_isUsed: %u\n", doc->V2G_Message.Body.WeldingDetectionReq_isUsed);
|
||||||
|
fprintf(fp, "WeldingDetectionRes_isUsed: %u\n", doc->V2G_Message.Body.WeldingDetectionRes_isUsed);
|
||||||
|
|
||||||
|
// CurrentDemandReq 상세 정보
|
||||||
|
if (doc->V2G_Message.Body.CurrentDemandReq_isUsed) {
|
||||||
|
fprintf(fp, "\n--- CurrentDemandReq Details ---\n");
|
||||||
|
|
||||||
|
// DC_EVStatus
|
||||||
|
fprintf(fp, "DC_EVStatus.EVReady: %u\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady);
|
||||||
|
fprintf(fp, "DC_EVStatus.EVErrorCode: %d\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode);
|
||||||
|
fprintf(fp, "DC_EVStatus.EVRESSSOC: %d\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC);
|
||||||
|
|
||||||
|
// EVTargetCurrent
|
||||||
|
fprintf(fp, "EVTargetCurrent.Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier);
|
||||||
|
fprintf(fp, "EVTargetCurrent.Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit);
|
||||||
|
fprintf(fp, "EVTargetCurrent.Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value);
|
||||||
|
|
||||||
|
// 선택적 필드들
|
||||||
|
fprintf(fp, "EVMaximumVoltageLimit_isUsed: %u\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed);
|
||||||
|
if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed) {
|
||||||
|
fprintf(fp, "EVMaximumVoltageLimit.Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier);
|
||||||
|
fprintf(fp, "EVMaximumVoltageLimit.Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Unit);
|
||||||
|
fprintf(fp, "EVMaximumVoltageLimit.Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "EVMaximumCurrentLimit_isUsed: %u\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed);
|
||||||
|
if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed) {
|
||||||
|
fprintf(fp, "EVMaximumCurrentLimit.Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Multiplier);
|
||||||
|
fprintf(fp, "EVMaximumCurrentLimit.Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Unit);
|
||||||
|
fprintf(fp, "EVMaximumCurrentLimit.Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "EVMaximumPowerLimit_isUsed: %u\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed);
|
||||||
|
if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed) {
|
||||||
|
fprintf(fp, "EVMaximumPowerLimit.Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Multiplier);
|
||||||
|
fprintf(fp, "EVMaximumPowerLimit.Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Unit);
|
||||||
|
fprintf(fp, "EVMaximumPowerLimit.Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "BulkChargingComplete_isUsed: %u\n", doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed);
|
||||||
|
if (doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed) {
|
||||||
|
fprintf(fp, "BulkChargingComplete: %u\n", doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChargingComplete (필수 필드)
|
||||||
|
fprintf(fp, "ChargingComplete: %u\n", doc->V2G_Message.Body.CurrentDemandReq.ChargingComplete);
|
||||||
|
|
||||||
|
fprintf(fp, "RemainingTimeToFullSoC_isUsed: %u\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed);
|
||||||
|
if (doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed) {
|
||||||
|
fprintf(fp, "RemainingTimeToFullSoC.Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Multiplier);
|
||||||
|
fprintf(fp, "RemainingTimeToFullSoC.Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Unit);
|
||||||
|
fprintf(fp, "RemainingTimeToFullSoC.Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "RemainingTimeToBulkSoC_isUsed: %u\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed);
|
||||||
|
if (doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed) {
|
||||||
|
fprintf(fp, "RemainingTimeToBulkSoC.Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Multiplier);
|
||||||
|
fprintf(fp, "RemainingTimeToBulkSoC.Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Unit);
|
||||||
|
fprintf(fp, "RemainingTimeToBulkSoC.Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EVTargetVoltage (필수 필드)
|
||||||
|
fprintf(fp, "EVTargetVoltage.Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier);
|
||||||
|
fprintf(fp, "EVTargetVoltage.Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit);
|
||||||
|
fprintf(fp, "EVTargetVoltage.Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
printf("✓ Structure dump saved to %s\n", filename);
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function to read EXI file
|
// Helper function to read EXI file
|
||||||
int readEXIFile(char* file, uint8_t* buffer, size_t buffer_size, size_t *bytes_read) {
|
int readEXIFile(char* file, uint8_t* buffer, size_t buffer_size, size_t *bytes_read) {
|
||||||
FILE *fp = fopen(file, "rb");
|
FILE *fp = fopen(file, "rb");
|
||||||
@@ -756,12 +906,6 @@ void print_iso1_xml_wireshark(struct iso1EXIDocument* doc) {
|
|||||||
printf("<ns4:Value>%d</ns4:Value>", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value);
|
printf("<ns4:Value>%d</ns4:Value>", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value);
|
||||||
printf("</ns3:EVTargetCurrent>");
|
printf("</ns3:EVTargetCurrent>");
|
||||||
|
|
||||||
printf("<ns3:EVTargetVoltage>");
|
|
||||||
printf("<ns4:Multiplier>%d</ns4:Multiplier>", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier);
|
|
||||||
printf("<ns4:Unit>%d</ns4:Unit>", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit);
|
|
||||||
printf("<ns4:Value>%d</ns4:Value>", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value);
|
|
||||||
printf("</ns3:EVTargetVoltage>");
|
|
||||||
|
|
||||||
if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed) {
|
if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed) {
|
||||||
printf("<ns3:EVMaximumVoltageLimit>");
|
printf("<ns3:EVMaximumVoltageLimit>");
|
||||||
printf("<ns4:Multiplier>%d</ns4:Multiplier>", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier);
|
printf("<ns4:Multiplier>%d</ns4:Multiplier>", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier);
|
||||||
@@ -808,6 +952,13 @@ void print_iso1_xml_wireshark(struct iso1EXIDocument* doc) {
|
|||||||
printf("</ns3:RemainingTimeToBulkSoC>");
|
printf("</ns3:RemainingTimeToBulkSoC>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EVTargetVoltage must come last according to EXI grammar
|
||||||
|
printf("<ns3:EVTargetVoltage>");
|
||||||
|
printf("<ns4:Multiplier>%d</ns4:Multiplier>", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier);
|
||||||
|
printf("<ns4:Unit>%d</ns4:Unit>", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit);
|
||||||
|
printf("<ns4:Value>%d</ns4:Value>", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value);
|
||||||
|
printf("</ns3:EVTargetVoltage>");
|
||||||
|
|
||||||
printf("</ns3:CurrentDemandReq>");
|
printf("</ns3:CurrentDemandReq>");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,14 +1150,29 @@ int main(int argc, char *argv[]) {
|
|||||||
free(xml_content);
|
free(xml_content);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Show encoding info only when redirecting to file (keeps terminal output clean)
|
|
||||||
struct stat stat_buf_debug;
|
// XML parsing debug info to stderr (optional)
|
||||||
int is_file_redirect = (fstat(fileno(stdout), &stat_buf_debug) == 0 && S_ISREG(stat_buf_debug.st_mode));
|
// fprintf(stderr, "=== XML Parsing Debug ===\\n");
|
||||||
if (is_file_redirect) {
|
// fprintf(stderr, "V2G_Message_isUsed: %s\\n", iso1Doc.V2G_Message_isUsed ? "true" : "false");
|
||||||
fprintf(stderr, "XML parsing successful\\n");
|
// fprintf(stderr, "SessionID length: %d\\n", iso1Doc.V2G_Message.Header.SessionID.bytesLen);
|
||||||
fprintf(stderr, "SessionID length: %d\\n", iso1Doc.V2G_Message.Header.SessionID.bytesLen);
|
// fprintf(stderr, "CurrentDemandReq_isUsed: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed ? "true" : "false");
|
||||||
fprintf(stderr, "CurrentDemandReq_isUsed: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed ? "true" : "false");
|
|
||||||
|
// Debug output disabled for clean hex-only output
|
||||||
|
/*
|
||||||
|
if (iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed) {
|
||||||
|
fprintf(stderr, "EVReady: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false");
|
||||||
|
fprintf(stderr, "EVErrorCode: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode);
|
||||||
|
fprintf(stderr, "EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC);
|
||||||
|
fprintf(stderr, "EVTargetCurrent: M=%d, U=%d, V=%d\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier,
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit,
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value);
|
||||||
|
fprintf(stderr, "EVTargetVoltage: M=%d, U=%d, V=%d\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier,
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit,
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
free(xml_content);
|
free(xml_content);
|
||||||
|
|
||||||
@@ -1018,32 +1184,29 @@ int main(int argc, char *argv[]) {
|
|||||||
stream.buffer = 0;
|
stream.buffer = 0;
|
||||||
stream.capacity = 0;
|
stream.capacity = 0;
|
||||||
|
|
||||||
|
// 구조체 덤프 (디버그용, 필요시 활성화)
|
||||||
|
// dump_iso1_document_to_file(&iso1Doc, "struct_xml.txt");
|
||||||
|
|
||||||
errn = encode_iso1ExiDocument(&stream, &iso1Doc);
|
errn = encode_iso1ExiDocument(&stream, &iso1Doc);
|
||||||
|
|
||||||
if (errn != 0) {
|
if (errn != 0) {
|
||||||
printf("Error encoding to EXI (error: %d)\\n", errn);
|
fprintf(stderr, "Error encoding to EXI (error: %d)\\n", errn);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if output is redirected (for Windows/MINGW compatibility)
|
// Check if output is redirected
|
||||||
// Use environment variable approach or check for redirection
|
|
||||||
char* term = getenv("TERM");
|
|
||||||
int use_hex_output = (term != NULL) || isatty(fileno(stdout));
|
|
||||||
|
|
||||||
// Also check if user specifically wants binary output by checking for redirection
|
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
if (fstat(fileno(stdout), &stat_buf) == 0 && S_ISREG(stat_buf.st_mode)) {
|
int is_redirected = (fstat(fileno(stdout), &stat_buf) == 0 && S_ISREG(stat_buf.st_mode));
|
||||||
use_hex_output = 0; // Regular file, use binary
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_hex_output) {
|
if (is_redirected) {
|
||||||
// Terminal output: show hex string only
|
// Redirected output: write binary data
|
||||||
|
fwrite(buffer, 1, pos, stdout);
|
||||||
|
} else {
|
||||||
|
// Terminal output: show hex string only (like XML decode mode)
|
||||||
for(size_t i = 0; i < pos; i++) {
|
for(size_t i = 0; i < pos; i++) {
|
||||||
printf("%02X", buffer[i]);
|
printf("%02X", buffer[i]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
|
||||||
// Redirected output: write binary data
|
|
||||||
fwrite(buffer, 1, pos, stdout);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1105,7 +1268,41 @@ int main(int argc, char *argv[]) {
|
|||||||
print_iso1_xml_wireshark(&iso1Doc);
|
print_iso1_xml_wireshark(&iso1Doc);
|
||||||
} else {
|
} else {
|
||||||
print_iso1_message(&iso1Doc);
|
print_iso1_message(&iso1Doc);
|
||||||
|
|
||||||
|
// Compare with expected structure
|
||||||
|
printf("\\n=== Original EXI Structure Debug ===\\n");
|
||||||
|
printf("V2G_Message_isUsed: %s\\n", iso1Doc.V2G_Message_isUsed ? "true" : "false");
|
||||||
|
printf("SessionID length: %d\\n", iso1Doc.V2G_Message.Header.SessionID.bytesLen);
|
||||||
|
printf("CurrentDemandReq_isUsed: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed ? "true" : "false");
|
||||||
|
|
||||||
|
if (iso1Doc.V2G_Message.Body.CurrentDemandReq_isUsed) {
|
||||||
|
printf("EVReady: %s\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false");
|
||||||
|
printf("EVErrorCode: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode);
|
||||||
|
printf("EVRESSSOC: %d\\n", iso1Doc.V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC);
|
||||||
|
printf("EVTargetCurrent: M=%d, U=%d, V=%d\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier,
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit,
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value);
|
||||||
|
printf("EVMaximumVoltageLimit_isUsed: %s\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed ? "true" : "false");
|
||||||
|
printf("EVMaximumCurrentLimit_isUsed: %s\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed ? "true" : "false");
|
||||||
|
printf("EVMaximumPowerLimit_isUsed: %s\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed ? "true" : "false");
|
||||||
|
printf("BulkChargingComplete_isUsed: %s\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed ? "true" : "false");
|
||||||
|
printf("RemainingTimeToFullSoC_isUsed: %s\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed ? "true" : "false");
|
||||||
|
printf("RemainingTimeToBulkSoC_isUsed: %s\\n",
|
||||||
|
iso1Doc.V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed ? "true" : "false");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 원본 EXI 디코딩 후 구조체 덤프 (분석 모드일 때만)
|
||||||
|
if (!xml_mode) {
|
||||||
|
dump_iso1_document_to_file(&iso1Doc, "struct_exi.txt");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
if (!xml_mode) printf("✗ ISO1 decode failed (error: %d)\\n", errn);
|
if (!xml_mode) printf("✗ ISO1 decode failed (error: %d)\\n", errn);
|
||||||
BIN
V2GDecoder.exe
Normal file
BIN
V2GDecoder.exe
Normal file
Binary file not shown.
@@ -1,7 +1,7 @@
|
|||||||
@echo off
|
@echo off
|
||||||
echo Building enhanced_exi_viewer...
|
echo Building V2GDecoder...
|
||||||
|
|
||||||
gcc -o enhanced_exi_viewer enhanced_exi_viewer.c ^
|
gcc -o V2GDecoder V2GDecoder.c ^
|
||||||
src/iso1/*.c ^
|
src/iso1/*.c ^
|
||||||
src/iso2/*.c ^
|
src/iso2/*.c ^
|
||||||
src/din/*.c ^
|
src/din/*.c ^
|
||||||
@@ -12,7 +12,7 @@ gcc -o enhanced_exi_viewer enhanced_exi_viewer.c ^
|
|||||||
-I./src/din
|
-I./src/din
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 0 (
|
if %ERRORLEVEL% EQU 0 (
|
||||||
echo Build successful! enhanced_exi_viewer.exe created.
|
echo Build successful! V2GDecoder.exe created.
|
||||||
) else (
|
) else (
|
||||||
echo Build failed with error code %ERRORLEVEL%
|
echo Build failed with error code %ERRORLEVEL%
|
||||||
)
|
)
|
||||||
|
|||||||
Binary file not shown.
29
minimal_test.xml
Normal file
29
minimal_test.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?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>
|
||||||
|
<ns3:CurrentDemandReq>
|
||||||
|
<ns3:DC_EVStatus>
|
||||||
|
<ns4:EVReady>true</ns4:EVReady>
|
||||||
|
<ns4:EVErrorCode>0</ns4:EVErrorCode>
|
||||||
|
<ns4:EVRESSSOC>100</ns4:EVRESSSOC>
|
||||||
|
</ns3:DC_EVStatus>
|
||||||
|
<ns3:EVTargetCurrent>
|
||||||
|
<ns4:Multiplier>0</ns4:Multiplier>
|
||||||
|
<ns4:Unit>3</ns4:Unit>
|
||||||
|
<ns4:Value>5</ns4:Value>
|
||||||
|
</ns3:EVTargetCurrent>
|
||||||
|
<ns3:ChargingComplete>true</ns3:ChargingComplete>
|
||||||
|
<ns3:EVTargetVoltage>
|
||||||
|
<ns4:Multiplier>0</ns4:Multiplier>
|
||||||
|
<ns4:Unit>4</ns4:Unit>
|
||||||
|
<ns4:Value>460</ns4:Value>
|
||||||
|
</ns3:EVTargetVoltage>
|
||||||
|
</ns3:CurrentDemandReq>
|
||||||
|
</ns1:Body>
|
||||||
|
</ns1:V2G_Message>
|
||||||
File diff suppressed because one or more lines are too long
46
struct_exi.txt
Normal file
46
struct_exi.txt
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
=== 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: 0
|
||||||
|
CurrentDemandRes_isUsed: 1
|
||||||
|
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
|
||||||
80
struct_xml.txt
Normal file
80
struct_xml.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