diff --git a/enhanced_exi_viewer.c b/enhanced_exi_viewer.c index 1f69dbb..dc15afe 100644 --- a/enhanced_exi_viewer.c +++ b/enhanced_exi_viewer.c @@ -1,519 +1,593 @@ #include #include #include +#include /* EXI codec headers */ #include "iso1EXIDatatypes.h" #include "iso1EXIDatatypesDecoder.h" +#include "iso1EXIDatatypesEncoder.h" #include "iso2EXIDatatypes.h" #include "iso2EXIDatatypesDecoder.h" +#include "iso2EXIDatatypesEncoder.h" #include "dinEXIDatatypes.h" #include "dinEXIDatatypesDecoder.h" +#include "dinEXIDatatypesEncoder.h" #include "ByteStream.h" #define BUFFER_SIZE 4096 -void print_session_id(uint8_t *bytes, size_t len) { - printf("SessionID: "); - for(size_t i = 0; i < len; i++) { - printf("%02X", bytes[i]); +// Helper function to convert char* string to exi_string_character_t* array +static int writeStringToEXIString(char* string, exi_string_character_t* exiString) { + int pos = 0; + while(string[pos] != '\0') { + exiString[pos] = string[pos]; + pos++; } - printf(" ("); - for(size_t i = 0; i < len; i++) { - if (bytes[i] >= 32 && bytes[i] <= 126) { - printf("%c", bytes[i]); - } else { - printf("."); + return pos; +} + +char* trim_whitespace(char* str) { + char* end; + while(isspace((unsigned char)*str)) str++; + if(*str == 0) return str; + end = str + strlen(str) - 1; + while(end > str && isspace((unsigned char)*end)) end--; + end[1] = '\0'; + return str; +} + +// Helper function to find XML tag content within a bounded section +char* find_tag_in_section(const char* section_start, const char* section_end, const char* tag) { + static char result[1024]; + char start_tag[256], end_tag[256]; + snprintf(start_tag, sizeof(start_tag), "<%s>", tag); + snprintf(end_tag, sizeof(end_tag), "", tag); + + // Search for tag within the bounded section + char* tag_start = strstr(section_start, start_tag); + if (!tag_start || tag_start >= section_end) { + return NULL; + } + + char* content_start = tag_start + strlen(start_tag); + if (content_start >= section_end) { + return NULL; + } + + char* tag_end = strstr(content_start, end_tag); + if (!tag_end || tag_end > section_end) { + return NULL; + } + + size_t len = tag_end - content_start; + if (len >= sizeof(result)) len = sizeof(result) - 1; + + strncpy(result, content_start, len); + result[len] = '\0'; + + char* trimmed = trim_whitespace(result); + return trimmed; +} + +// Helper function to find XML tag content +char* find_tag_content(const char* xml, const char* tag) { + static char result[1024]; + char start_tag[256], end_tag[256]; + snprintf(start_tag, sizeof(start_tag), "<%s>", tag); + snprintf(end_tag, sizeof(end_tag), "", tag); + + char* start = strstr(xml, start_tag); + if (!start) return NULL; + start += strlen(start_tag); + + char* end = strstr(start, end_tag); + if (!end) return NULL; + + size_t len = end - start; + if (len >= sizeof(result)) len = sizeof(result) - 1; + + strncpy(result, start, len); + result[len] = '\0'; + return trim_whitespace(result); +} + +int parse_session_id(const char* hex_str, uint8_t* bytes, size_t* len) { + size_t hex_len = strlen(hex_str); + if (hex_len % 2 != 0) return -1; + + *len = hex_len / 2; + for (size_t i = 0; i < *len; i++) { + unsigned int byte; + if (sscanf(&hex_str[i*2], "%2x", &byte) != 1) return -1; + bytes[i] = (uint8_t)byte; + } + return 0; +} + +// Parse PhysicalValue from section bounded XML +void parse_physical_value_from_section(const char* section_start, const char* section_end, struct iso1PhysicalValueType* pv) { + // Copy the found values to local variables to avoid static buffer overwriting + char mult_str[64] = {0}; + char unit_str[64] = {0}; + char value_str[64] = {0}; + + char* mult = find_tag_in_section(section_start, section_end, "Multiplier"); + if (mult) strncpy(mult_str, mult, sizeof(mult_str)-1); + + char* unit = find_tag_in_section(section_start, section_end, "Unit"); + if (unit) strncpy(unit_str, unit, sizeof(unit_str)-1); + + char* value = find_tag_in_section(section_start, section_end, "Value"); + if (value) strncpy(value_str, value, sizeof(value_str)-1); + + // Now parse the copied values + if (mult) pv->Multiplier = atoi(mult_str); + if (unit) pv->Unit = atoi(unit_str); + if (value) pv->Value = atoi(value_str); +} + +// Parse XML to ISO1 document for encoding +int parse_xml_to_iso1(const char* xml_content, struct iso1EXIDocument* doc) { + init_iso1EXIDocument(doc); + + // Find SessionID + char* session_id_str = find_tag_content(xml_content, "SessionID"); + if (session_id_str) { + size_t len; + if (parse_session_id(session_id_str, doc->V2G_Message.Header.SessionID.bytes, &len) == 0) { + doc->V2G_Message.Header.SessionID.bytesLen = len; + doc->V2G_Message_isUsed = 1; } } - printf(")\n"); + + // Check for CurrentDemandReq + if (strstr(xml_content, "") || strstr(xml_content, "")) { + doc->V2G_Message.Body.CurrentDemandReq_isUsed = 1; + init_iso1CurrentDemandReqType(&doc->V2G_Message.Body.CurrentDemandReq); + + // Parse DC_EVStatus + char* ev_ready = find_tag_content(xml_content, "EVReady"); + if (ev_ready) { + doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady = (strcmp(ev_ready, "true") == 0); + } + + char* ev_error = find_tag_content(xml_content, "EVErrorCode"); + if (ev_error) { + if (strcmp(ev_error, "NO_ERROR") == 0) { + doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode = 0; + } else { + doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode = atoi(ev_error); + } + } + + char* ev_soc = find_tag_content(xml_content, "EVRESSSOC"); + if (ev_soc) { + doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC = atoi(ev_soc); + } + + // Parse EVTargetCurrent using bounded section approach + char* current_section = strstr(xml_content, ""); + if (!current_section) current_section = strstr(xml_content, ""); + if (current_section) { + char* current_end = strstr(current_section, ""); + if (!current_end) current_end = strstr(current_section, ""); + if (current_end) { + parse_physical_value_from_section(current_section, current_end, &doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent); + } + } + + // Parse EVTargetVoltage using bounded section approach + char* voltage_section = strstr(xml_content, ""); + if (!voltage_section) voltage_section = strstr(xml_content, ""); + if (voltage_section) { + char* voltage_end = strstr(voltage_section, ""); + if (!voltage_end) voltage_end = strstr(voltage_section, ""); + if (voltage_end) { + parse_physical_value_from_section(voltage_section, voltage_end, &doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage); + } + } + + // Parse ChargingComplete + char* charging_complete = find_tag_content(xml_content, "ChargingComplete"); + if (charging_complete) { + doc->V2G_Message.Body.CurrentDemandReq.ChargingComplete = (strcmp(charging_complete, "true") == 0); + } + + // Parse optional fields if present + if (strstr(xml_content, "") || strstr(xml_content, "")) { + doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed = 1; + char* max_volt_section = strstr(xml_content, ""); + if (!max_volt_section) max_volt_section = strstr(xml_content, ""); + char* max_volt_end = strstr(max_volt_section, ""); + if (!max_volt_end) max_volt_end = strstr(max_volt_section, ""); + if (max_volt_section && max_volt_end) { + parse_physical_value_from_section(max_volt_section, max_volt_end, &doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit); + } + } + + if (strstr(xml_content, "") || strstr(xml_content, "")) { + doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed = 1; + char* max_curr_section = strstr(xml_content, ""); + if (!max_curr_section) max_curr_section = strstr(xml_content, ""); + char* max_curr_end = strstr(max_curr_section, ""); + if (!max_curr_end) max_curr_end = strstr(max_curr_section, ""); + if (max_curr_section && max_curr_end) { + parse_physical_value_from_section(max_curr_section, max_curr_end, &doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit); + } + } + + if (strstr(xml_content, "") || strstr(xml_content, "")) { + doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed = 1; + char* max_power_section = strstr(xml_content, ""); + if (!max_power_section) max_power_section = strstr(xml_content, ""); + char* max_power_end = strstr(max_power_section, ""); + if (!max_power_end) max_power_end = strstr(max_power_section, ""); + if (max_power_section && max_power_end) { + parse_physical_value_from_section(max_power_section, max_power_end, &doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit); + } + } + + // Parse BulkChargingComplete + char* bulk_charging_complete = find_tag_content(xml_content, "BulkChargingComplete"); + if (bulk_charging_complete) { + doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed = 1; + doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete = (strcmp(bulk_charging_complete, "true") == 0); + } + + // Parse remaining time fields + if (strstr(xml_content, "") || strstr(xml_content, "")) { + doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed = 1; + char* time_section = strstr(xml_content, ""); + if (!time_section) time_section = strstr(xml_content, ""); + char* time_end = strstr(time_section, ""); + if (!time_end) time_end = strstr(time_section, ""); + if (time_section && time_end) { + parse_physical_value_from_section(time_section, time_end, &doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC); + } + } + + if (strstr(xml_content, "") || strstr(xml_content, "")) { + doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed = 1; + char* bulk_time_section = strstr(xml_content, ""); + if (!bulk_time_section) bulk_time_section = strstr(xml_content, ""); + char* bulk_time_end = strstr(bulk_time_section, ""); + if (!bulk_time_end) bulk_time_end = strstr(bulk_time_section, ""); + if (bulk_time_section && bulk_time_end) { + parse_physical_value_from_section(bulk_time_section, bulk_time_end, &doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC); + } + } + + return 0; + } + + return -1; // Unsupported message type } -void print_xml_header() { +// Helper function to read EXI file +int readEXIFile(char* file, uint8_t* buffer, size_t buffer_size, size_t *bytes_read) { + FILE *fp = fopen(file, "rb"); + if (fp == NULL) { + return -1; + } + + *bytes_read = fread(buffer, 1, buffer_size, fp); + fclose(fp); + + if (*bytes_read == 0) { + return -1; + } + + return 0; +} + +// Helper functions for Wireshark XML output +const char* get_unit_string(int unit) { + switch(unit) { + case 2: return "s"; // seconds + case 3: return "A"; // amperes + case 4: return "V"; // volts + case 5: return "W"; // watts + default: return ""; // fallback to number + } +} + +const char* get_error_string(int error) { + switch(error) { + case 0: return "NO_ERROR"; + default: return ""; // fallback to number + } +} + +void print_xml_header_wireshark() { printf("\n"); - printf("\n"); + printf("\n"); } -void print_xml_footer() { - printf("\n"); +void print_xml_footer_wireshark() { + printf(""); } -void print_session_id_xml(uint8_t *bytes, size_t len) { - printf(" "); - for(size_t i = 0; i < len; i++) { - printf("%02X", bytes[i]); +void print_iso1_xml_wireshark(struct iso1EXIDocument* doc) { + print_xml_header_wireshark(); + + printf(""); + for(int i = 0; i < doc->V2G_Message.Header.SessionID.bytesLen; i++) { + printf("%02X", doc->V2G_Message.Header.SessionID.bytes[i]); } - printf("\n"); -} - -void print_iso1_xml(struct iso1EXIDocument *doc) { - if (!doc->V2G_Message_isUsed) return; + printf(""); - print_xml_header(); - - // Header - printf("
\n"); - print_session_id_xml(doc->V2G_Message.Header.SessionID.bytes, - doc->V2G_Message.Header.SessionID.bytesLen); - - if (doc->V2G_Message.Header.Notification_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Header.Notification.FaultCode); - printf(" %s\n", doc->V2G_Message.Header.Notification.FaultMsg.characters); - printf(" \n"); - } - printf("
\n"); - - // Body - printf(" \n"); + printf(""); if (doc->V2G_Message.Body.CurrentDemandRes_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.ResponseCode); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSENotification); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.NotificationMaxDelay); - if (doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus_isUsed) { - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus); + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.ResponseCode); + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus); + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEStatusCode); + printf(""); + + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Multiplier); + const char* unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Unit); } - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEStatusCode); - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Value); - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Value); - printf(" \n"); - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSECurrentLimitAchieved ? "true" : "false"); - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEVoltageLimitAchieved ? "true" : "false"); - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPowerLimitAchieved ? "true" : "false"); - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Value); - printf(" \n"); + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Value); + printf(""); + + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Multiplier); + unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Unit); } - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Value); - printf(" \n"); - } - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Value); - printf(" \n"); - } - printf(" %.*s\n", + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Value); + printf(""); + + printf("%s", doc->V2G_Message.Body.CurrentDemandRes.EVSECurrentLimitAchieved ? "true" : "false"); + printf("%s", doc->V2G_Message.Body.CurrentDemandRes.EVSEVoltageLimitAchieved ? "true" : "false"); + printf("%s", doc->V2G_Message.Body.CurrentDemandRes.EVSEPowerLimitAchieved ? "true" : "false"); + printf("%.*s", doc->V2G_Message.Body.CurrentDemandRes.EVSEID.charactersLen, doc->V2G_Message.Body.CurrentDemandRes.EVSEID.characters); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.SAScheduleTupleID); - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo_isUsed) { - printf(" \n"); - printf(" %.*s\n", - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterID.charactersLen, - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterID.characters); - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterReading_isUsed) { - printf(" %llu\n", - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterReading); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading_isUsed) { - printf(" "); - for(int i = 0; i < doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading.bytes[i]); - } - printf("\n"); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterStatus_isUsed) { - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterStatus); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.TMeter_isUsed) { - printf(" %lld\n", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.TMeter); - } - printf(" \n"); - } - if (doc->V2G_Message.Body.CurrentDemandRes.ReceiptRequired_isUsed) { - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandRes.ReceiptRequired ? "true" : "false"); - } - printf(" \n"); + printf("%d", doc->V2G_Message.Body.CurrentDemandRes.SAScheduleTupleID); + printf(""); } else if (doc->V2G_Message.Body.CurrentDemandReq_isUsed) { - printf(" \n"); - printf(" \n"); - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC); - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value); - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value); - printf(" \n"); + printf(""); + printf(""); + printf("%s", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false"); + + const char* error_str = get_error_string(doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode); + if (strlen(error_str) > 0) { + printf("%s", error_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode); + } + + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC); + printf(""); + + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier); + const char* unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit); + } + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value); + printf(""); + + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier); + unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit); + } + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value); + printf(""); + if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Value); - printf(" \n"); + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier); + unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Unit); + } + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Value); + printf(""); } + if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Value); - printf(" \n"); + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Multiplier); + unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Unit); + } + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Value); + printf(""); } + if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Value); - printf(" \n"); + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Multiplier); + unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Unit); + } + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Value); + printf(""); } + if (doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed) { - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete ? "true" : "false"); + printf("%s", doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete ? "true" : "false"); } - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandReq.ChargingComplete ? "true" : "false"); + + printf("%s", doc->V2G_Message.Body.CurrentDemandReq.ChargingComplete ? "true" : "false"); + if (doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Value); - printf(" \n"); + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Multiplier); + unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Unit); + } + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Value); + printf(""); } + if (doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Value); - printf(" \n"); + printf(""); + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Multiplier); + unit_str = get_unit_string(doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Unit); + if (strlen(unit_str) > 0) { + printf("%s", unit_str); + } else { + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Unit); + } + printf("%d", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Value); + printf(""); } - printf(" \n"); - } - else { - printf(" \n"); + + printf("
"); } - printf(" \n"); - print_xml_footer(); + printf(""); + print_xml_footer_wireshark(); } -void print_iso1_message(struct iso1EXIDocument *doc) { - printf("=== ISO1 V2G Message ===\n"); +void print_iso1_message(struct iso1EXIDocument* doc) { + printf("=== ISO 15118-2 V2G Message Analysis ===\n"); + printf("Message Type: ISO1 (2013)\n"); + printf("V2G_Message_isUsed: %s\n", doc->V2G_Message_isUsed ? "true" : "false"); if (doc->V2G_Message_isUsed) { - // Print Header - printf("Header:\n"); - print_session_id(doc->V2G_Message.Header.SessionID.bytes, - doc->V2G_Message.Header.SessionID.bytesLen); + printf("\n--- Header ---\n"); + printf("SessionID: "); + for(int i = 0; i < doc->V2G_Message.Header.SessionID.bytesLen; i++) { + printf("%02X", doc->V2G_Message.Header.SessionID.bytes[i]); + } + printf(" ("); + for(int i = 0; i < doc->V2G_Message.Header.SessionID.bytesLen; i++) { + if (doc->V2G_Message.Header.SessionID.bytes[i] >= 32 && doc->V2G_Message.Header.SessionID.bytes[i] <= 126) { + printf("%c", doc->V2G_Message.Header.SessionID.bytes[i]); + } else { + printf("."); + } + } + printf(")\n"); - if (doc->V2G_Message.Header.Notification_isUsed) { - printf(" Notification: FaultCode=%d, FaultMsg=%s\n", - doc->V2G_Message.Header.Notification.FaultCode, - doc->V2G_Message.Header.Notification.FaultMsg.characters); - } + printf("\n--- Body ---\n"); - printf("\nBody:\n"); - - // Check all possible message types - if (doc->V2G_Message.Body.SessionSetupReq_isUsed) { - printf(" Message Type: SessionSetupReq\n"); - printf(" EVCCID: "); - for(size_t i = 0; i < doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i]); - } - printf(" ("); - for(size_t i = 0; i < doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytesLen; i++) { - if (doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i] >= 32 && - doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i] <= 126) { - printf("%c", doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i]); - } else { - printf("."); - } - } - printf(")\n"); - } - else if (doc->V2G_Message.Body.SessionSetupRes_isUsed) { - printf(" Message Type: SessionSetupRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.SessionSetupRes.ResponseCode); - printf(" EVSEID: %s\n", doc->V2G_Message.Body.SessionSetupRes.EVSEID.characters); - if (doc->V2G_Message.Body.SessionSetupRes.EVSETimeStamp_isUsed) { - printf(" EVSETimeStamp: %ld\n", doc->V2G_Message.Body.SessionSetupRes.EVSETimeStamp); - } - } - else if (doc->V2G_Message.Body.ServiceDiscoveryReq_isUsed) { - printf(" Message Type: ServiceDiscoveryReq\n"); - } - else if (doc->V2G_Message.Body.ServiceDiscoveryRes_isUsed) { - printf(" Message Type: ServiceDiscoveryRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.ServiceDiscoveryRes.ResponseCode); - } - else if (doc->V2G_Message.Body.ServiceDetailReq_isUsed) { - printf(" Message Type: ServiceDetailReq\n"); - printf(" ServiceID: %d\n", doc->V2G_Message.Body.ServiceDetailReq.ServiceID); - } - else if (doc->V2G_Message.Body.ServiceDetailRes_isUsed) { - printf(" Message Type: ServiceDetailRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.ServiceDetailRes.ResponseCode); - } - else if (doc->V2G_Message.Body.PaymentServiceSelectionReq_isUsed) { - printf(" Message Type: PaymentServiceSelectionReq\n"); - printf(" SelectedPaymentOption: %d\n", doc->V2G_Message.Body.PaymentServiceSelectionReq.SelectedPaymentOption); - } - else if (doc->V2G_Message.Body.PaymentServiceSelectionRes_isUsed) { - printf(" Message Type: PaymentServiceSelectionRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.PaymentServiceSelectionRes.ResponseCode); - } - else if (doc->V2G_Message.Body.AuthorizationReq_isUsed) { - printf(" Message Type: AuthorizationReq\n"); - if (doc->V2G_Message.Body.AuthorizationReq.Id_isUsed) { - printf(" ID: %s\n", doc->V2G_Message.Body.AuthorizationReq.Id.characters); - } - if (doc->V2G_Message.Body.AuthorizationReq.GenChallenge_isUsed) { - printf(" GenChallenge: "); - for(size_t i = 0; i < doc->V2G_Message.Body.AuthorizationReq.GenChallenge.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.AuthorizationReq.GenChallenge.bytes[i]); - } - printf("\n"); - } - } - else if (doc->V2G_Message.Body.AuthorizationRes_isUsed) { - printf(" Message Type: AuthorizationRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.AuthorizationRes.ResponseCode); - printf(" EVSEProcessing: %d\n", doc->V2G_Message.Body.AuthorizationRes.EVSEProcessing); - } - else if (doc->V2G_Message.Body.ChargeParameterDiscoveryReq_isUsed) { - printf(" Message Type: ChargeParameterDiscoveryReq\n"); - } - else if (doc->V2G_Message.Body.ChargeParameterDiscoveryRes_isUsed) { - printf(" Message Type: ChargeParameterDiscoveryRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.ChargeParameterDiscoveryRes.ResponseCode); - } - else if (doc->V2G_Message.Body.CableCheckReq_isUsed) { - printf(" Message Type: CableCheckReq\n"); - } - else if (doc->V2G_Message.Body.CableCheckRes_isUsed) { - printf(" Message Type: CableCheckRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.CableCheckRes.ResponseCode); - } - else if (doc->V2G_Message.Body.PreChargeReq_isUsed) { - printf(" Message Type: PreChargeReq\n"); - printf(" EVTargetVoltage: %d\n", doc->V2G_Message.Body.PreChargeReq.EVTargetVoltage.Value); - printf(" EVTargetCurrent: %d\n", doc->V2G_Message.Body.PreChargeReq.EVTargetCurrent.Value); - } - else if (doc->V2G_Message.Body.PreChargeRes_isUsed) { - printf(" Message Type: PreChargeRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.PreChargeRes.ResponseCode); - } - else if (doc->V2G_Message.Body.PowerDeliveryReq_isUsed) { - printf(" Message Type: PowerDeliveryReq\n"); - printf(" ChargeProgress: %d\n", doc->V2G_Message.Body.PowerDeliveryReq.ChargeProgress); - printf(" SAScheduleTupleID: %d\n", doc->V2G_Message.Body.PowerDeliveryReq.SAScheduleTupleID); - } - else if (doc->V2G_Message.Body.PowerDeliveryRes_isUsed) { - printf(" Message Type: PowerDeliveryRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.PowerDeliveryRes.ResponseCode); - } - else if (doc->V2G_Message.Body.ChargingStatusReq_isUsed) { - printf(" Message Type: ChargingStatusReq\n"); - } - else if (doc->V2G_Message.Body.ChargingStatusRes_isUsed) { - printf(" Message Type: ChargingStatusRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.ChargingStatusRes.ResponseCode); - } - else if (doc->V2G_Message.Body.MeteringReceiptReq_isUsed) { - printf(" Message Type: MeteringReceiptReq\n"); - } - else if (doc->V2G_Message.Body.MeteringReceiptRes_isUsed) { - printf(" Message Type: MeteringReceiptRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.MeteringReceiptRes.ResponseCode); - } - else if (doc->V2G_Message.Body.SessionStopReq_isUsed) { - printf(" Message Type: SessionStopReq\n"); - printf(" ChargingSession: %d\n", doc->V2G_Message.Body.SessionStopReq.ChargingSession); - } - else if (doc->V2G_Message.Body.SessionStopRes_isUsed) { - printf(" Message Type: SessionStopRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.SessionStopRes.ResponseCode); - } - else if (doc->V2G_Message.Body.CurrentDemandReq_isUsed) { - printf(" Message Type: CurrentDemandReq\n"); - printf(" DC_EVStatus:\n"); - printf(" EVReady: %s\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false"); - printf(" EVErrorCode: %d\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode); - printf(" EVRESSSOC: %d%%\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC); - printf(" EVTargetCurrent: %d A (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value, - doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier, - doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit); - printf(" EVTargetVoltage: %d V (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value, - doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier, - doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit); - if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed) { - printf(" EVMaximumVoltageLimit: %d V (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Value, - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier, - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Unit); - } - if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed) { - printf(" EVMaximumCurrentLimit: %d A (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Value, - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Multiplier, - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Unit); - } - if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed) { - printf(" EVMaximumPowerLimit: %d W (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Value, - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Multiplier, - doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Unit); - } - if (doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed) { - printf(" BulkChargingComplete: %s\n", doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete ? "true" : "false"); - } - printf(" ChargingComplete: %s\n", doc->V2G_Message.Body.CurrentDemandReq.ChargingComplete ? "true" : "false"); - if (doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed) { - printf(" RemainingTimeToFullSoC: %d s (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Value, - doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Multiplier, - doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Unit); - } - if (doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed) { - printf(" RemainingTimeToBulkSoC: %d s (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Value, - doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Multiplier, - doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Unit); - } - } - else if (doc->V2G_Message.Body.CurrentDemandRes_isUsed) { - printf(" Message Type: CurrentDemandRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.CurrentDemandRes.ResponseCode); - printf(" DC_EVSEStatus:\n"); - printf(" EVSENotification: %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSENotification); - printf(" NotificationMaxDelay: %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.NotificationMaxDelay); - if (doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus_isUsed) { - printf(" EVSEIsolationStatus: %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus); - } - printf(" EVSEStatusCode: %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEStatusCode); - printf(" EVSEPresentVoltage: %d V (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Value, - doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Multiplier, - doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Unit); - printf(" EVSEPresentCurrent: %d A (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Value, - doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Multiplier, - doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Unit); - printf(" EVSECurrentLimitAchieved: %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSECurrentLimitAchieved ? "true" : "false"); - printf(" EVSEVoltageLimitAchieved: %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEVoltageLimitAchieved ? "true" : "false"); - printf(" EVSEPowerLimitAchieved: %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPowerLimitAchieved ? "true" : "false"); - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit_isUsed) { - printf(" EVSEMaximumVoltageLimit: %d V (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Value, - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Multiplier, - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Unit); - } - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit_isUsed) { - printf(" EVSEMaximumCurrentLimit: %d A (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Value, - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Multiplier, - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Unit); - } - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit_isUsed) { - printf(" EVSEMaximumPowerLimit: %d W (Multiplier: %d, Unit: %d)\n", - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Value, - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Multiplier, - doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Unit); - } - printf(" EVSEID: %.*s\n", + if (doc->V2G_Message.Body.CurrentDemandRes_isUsed) { + printf("Message Type: CurrentDemandRes\n"); + printf("ResponseCode: %d\n", doc->V2G_Message.Body.CurrentDemandRes.ResponseCode); + + printf("\nDC_EVSEStatus:\n"); + printf(" EVSEIsolationStatus: %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus); + printf(" EVSEStatusCode: %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEStatusCode); + + printf("\nEVSEPresentVoltage:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Value); + + printf("\nEVSEPresentCurrent:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Value); + + printf("\nLimit Status:\n"); + printf(" CurrentLimitAchieved: %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSECurrentLimitAchieved ? "true" : "false"); + printf(" VoltageLimitAchieved: %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEVoltageLimitAchieved ? "true" : "false"); + printf(" PowerLimitAchieved: %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPowerLimitAchieved ? "true" : "false"); + + printf("\nEVSEID: %.*s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEID.charactersLen, doc->V2G_Message.Body.CurrentDemandRes.EVSEID.characters); - printf(" SAScheduleTupleID: %d\n", doc->V2G_Message.Body.CurrentDemandRes.SAScheduleTupleID); - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo_isUsed) { - printf(" MeterInfo:\n"); - printf(" MeterID: %.*s\n", - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterID.charactersLen, - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterID.characters); - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterReading_isUsed) { - printf(" MeterReading: %llu Wh\n", - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterReading); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading_isUsed) { - printf(" SigMeterReading: "); - for(int i = 0; i < doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading.bytes[i]); - } - printf("\n"); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterStatus_isUsed) { - printf(" MeterStatus: %d\n", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterStatus); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.TMeter_isUsed) { - printf(" TMeter: %lld\n", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.TMeter); - } - } - if (doc->V2G_Message.Body.CurrentDemandRes.ReceiptRequired_isUsed) { - printf(" ReceiptRequired: %s\n", doc->V2G_Message.Body.CurrentDemandRes.ReceiptRequired ? "true" : "false"); - } + printf("SAScheduleTupleID: %d\n", doc->V2G_Message.Body.CurrentDemandRes.SAScheduleTupleID); } - else if (doc->V2G_Message.Body.WeldingDetectionReq_isUsed) { - printf(" Message Type: WeldingDetectionReq\n"); - } - else if (doc->V2G_Message.Body.WeldingDetectionRes_isUsed) { - printf(" Message Type: WeldingDetectionRes\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.WeldingDetectionRes.ResponseCode); + else if (doc->V2G_Message.Body.CurrentDemandReq_isUsed) { + printf("Message Type: CurrentDemandReq\n"); + + printf("\nDC_EVStatus:\n"); + printf(" EVReady: %s\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVReady ? "true" : "false"); + printf(" EVErrorCode: %d\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVErrorCode); + printf(" EVRESSSOC: %d%%\n", doc->V2G_Message.Body.CurrentDemandReq.DC_EVStatus.EVRESSSOC); + + printf("\nEVTargetCurrent:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value); + + printf("\nEVTargetVoltage:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value); + + if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed) { + printf("\nEVMaximumVoltageLimit:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Value); + } + + if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed) { + printf("\nEVMaximumCurrentLimit:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Value); + } + + if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed) { + printf("\nEVMaximumPowerLimit:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Value); + } + + if (doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete_isUsed) { + printf("\nBulkChargingComplete: %s\n", doc->V2G_Message.Body.CurrentDemandReq.BulkChargingComplete ? "true" : "false"); + } + + printf("ChargingComplete: %s\n", doc->V2G_Message.Body.CurrentDemandReq.ChargingComplete ? "true" : "false"); + + if (doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC_isUsed) { + printf("\nRemainingTimeToFullSoC:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToFullSoC.Value); + } + + if (doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC_isUsed) { + printf("\nRemainingTimeToBulkSoC:\n"); + printf(" Multiplier: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Multiplier); + printf(" Unit: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Unit); + printf(" Value: %d\n", doc->V2G_Message.Body.CurrentDemandReq.RemainingTimeToBulkSoC.Value); + } } else { - printf(" Message Type: Unknown or unhandled message type\n"); - printf(" Debug: Checking which flags are set...\n"); - // Debug output to see which flags might be set - } - } - printf("\n"); -} - -void print_iso2_message(struct iso2EXIDocument *doc) { - printf("=== ISO2 V2G Message ===\n"); - - if (doc->V2G_Message_isUsed) { - printf("Header:\n"); - print_session_id(doc->V2G_Message.Header.SessionID.bytes, - doc->V2G_Message.Header.SessionID.bytesLen); - - printf("\nBody:\n"); - if (doc->V2G_Message.Body.SessionSetupReq_isUsed) { - printf(" Message Type: SessionSetupReq\n"); - printf(" EVCCID: "); - for(size_t i = 0; i < doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i]); - } - printf(" ("); - for(size_t i = 0; i < doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytesLen; i++) { - if (doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i] >= 32 && - doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i] <= 126) { - printf("%c", doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i]); - } else { - printf("."); - } - } - printf(")\n"); - } - // Add more ISO2 message types as needed - else { - printf(" Message Type: Other ISO2 message (not fully implemented)\n"); + printf("Message Type: Other message type (not fully supported)\n"); } } printf("\n"); @@ -521,6 +595,7 @@ void print_iso2_message(struct iso2EXIDocument *doc) { int main(int argc, char *argv[]) { int xml_mode = 0; + int encode_mode = 0; char *filename = NULL; if (argc == 2) { @@ -528,11 +603,15 @@ int main(int argc, char *argv[]) { } else if (argc == 3 && strcmp(argv[1], "-decode") == 0) { xml_mode = 1; filename = argv[2]; + } else if (argc == 3 && strcmp(argv[1], "-encode") == 0) { + encode_mode = 1; + filename = argv[2]; } else { - printf("Usage: %s [-decode] input.exi\n", argv[0]); - printf("Enhanced EXI viewer with detailed message parsing\n"); - printf(" -decode Output in XML format\n"); - printf(" (default) Output detailed analysis\n"); + printf("Usage: %s [-decode|-encode] input_file\\n", argv[0]); + printf("Enhanced EXI viewer with XML conversion capabilities\\n"); + printf(" -decode Convert EXI to Wireshark-style XML format\\n"); + printf(" -encode Convert XML to EXI format\\n"); + printf(" (default) Analyze EXI with detailed output\\n"); return -1; } @@ -550,21 +629,74 @@ int main(int argc, char *argv[]) { init_iso2EXIDocument(&iso2Doc); init_dinEXIDocument(&dinDoc); - // Read file - errn = readBytesFromFile(filename, buffer, BUFFER_SIZE, &pos); + // Handle encode mode (XML to EXI) + if (encode_mode) { + // Read XML file + FILE* xml_file = fopen(filename, "r"); + if (!xml_file) { + printf("Error opening XML file: %s\\n", filename); + return -1; + } + + // Read entire XML content + fseek(xml_file, 0, SEEK_END); + long xml_size = ftell(xml_file); + fseek(xml_file, 0, SEEK_SET); + + char* xml_content = malloc(xml_size + 1); + if (!xml_content) { + printf("Error allocating memory for XML content\\n"); + fclose(xml_file); + return -1; + } + + fread(xml_content, 1, xml_size, xml_file); + xml_content[xml_size] = '\0'; + fclose(xml_file); + + // Parse XML to ISO1 document structure + if (parse_xml_to_iso1(xml_content, &iso1Doc) != 0) { + printf("Error parsing XML file\\n"); + free(xml_content); + return -1; + } + + free(xml_content); + + // Encode to EXI + pos = 0; + stream.size = BUFFER_SIZE; + stream.data = buffer; + stream.pos = &pos; + stream.buffer = 0; + stream.capacity = 0; + + errn = encode_iso1ExiDocument(&stream, &iso1Doc); + if (errn != 0) { + printf("Error encoding to EXI (error: %d)\\n", errn); + return -1; + } + + // Write EXI data to stdout (binary) + fwrite(buffer, 1, pos, stdout); + return 0; + } + + // Read EXI file for decode/analysis mode + errn = readEXIFile(filename, buffer, BUFFER_SIZE, &pos); if (errn != 0) { - printf("Error reading file: %s\n", filename); + printf("Error reading file: %s\\n", filename); return -1; } if (!xml_mode) { - printf("File: %s (%zu bytes)\n", filename, pos); + printf("File: %s (%zu bytes)\\n", filename, pos); printf("Raw hex data: "); for(size_t i = 0; i < (pos > 32 ? 32 : pos); i++) { printf("%02X ", buffer[i]); } if (pos > 32) printf("..."); - printf("\n\n"); + printf("\\n\\n"); } // Setup stream @@ -577,50 +709,54 @@ int main(int argc, char *argv[]) { // Try ISO1 first pos = 0; - if (!xml_mode) printf("Trying ISO1 decoder...\n"); + if (!xml_mode) printf("Trying ISO1 decoder...\\n"); errn = decode_iso1ExiDocument(&stream, &iso1Doc); if (errn == 0) { - if (!xml_mode) printf("✓ Successfully decoded as ISO1\n\n"); + if (!xml_mode) printf("✓ Successfully decoded as ISO1\\n\\n"); if (xml_mode) { - print_iso1_xml(&iso1Doc); + print_iso1_xml_wireshark(&iso1Doc); } else { print_iso1_message(&iso1Doc); } return 0; } else { - if (!xml_mode) printf("✗ ISO1 decode failed (error: %d)\n", errn); + if (!xml_mode) printf("✗ ISO1 decode failed (error: %d)\\n", errn); } // Try ISO2 pos = 0; - if (!xml_mode) printf("Trying ISO2 decoder...\n"); + if (!xml_mode) printf("Trying ISO2 decoder...\\n"); errn = decode_iso2ExiDocument(&stream, &iso2Doc); if (errn == 0) { - if (!xml_mode) printf("✓ Successfully decoded as ISO2\n\n"); - print_iso2_message(&iso2Doc); + if (!xml_mode) printf("✓ Successfully decoded as ISO2\\n\\n"); + if (xml_mode) { + printf("ISO2 XML output not implemented for Wireshark format\\n"); + } else { + printf("ISO2 analysis not fully implemented\\n"); + } return 0; } else { - if (!xml_mode) printf("✗ ISO2 decode failed (error: %d)\n", errn); + if (!xml_mode) printf("✗ ISO2 decode failed (error: %d)\\n", errn); } // Try DIN pos = 0; - if (!xml_mode) printf("Trying DIN decoder...\n"); + if (!xml_mode) printf("Trying DIN decoder...\\n"); errn = decode_dinExiDocument(&stream, &dinDoc); if (errn == 0) { if (!xml_mode) { - printf("✓ Successfully decoded as DIN\n\n"); - printf("=== DIN V2G Message ===\n"); + printf("✓ Successfully decoded as DIN\\n\\n"); + printf("=== DIN V2G Message ===\\n"); // Add DIN message printing as needed } return 0; } else { - if (!xml_mode) printf("✗ DIN decode failed (error: %d)\n", errn); + if (!xml_mode) printf("✗ DIN decode failed (error: %d)\\n", errn); } if (!xml_mode) { - printf("\n❌ Could not decode EXI file with any supported codec\n"); - printf("Supported formats: ISO1, ISO2, DIN\n"); + printf("\\n❌ Could not decode EXI file with any supported codec\\n"); + printf("Supported formats: ISO1, ISO2, DIN\\n"); } return -1; diff --git a/enhanced_exi_viewer.exe b/enhanced_exi_viewer.exe index 304097d..88cfaa4 100644 Binary files a/enhanced_exi_viewer.exe and b/enhanced_exi_viewer.exe differ diff --git a/enhanced_exi_viewer.o b/enhanced_exi_viewer.o new file mode 100644 index 0000000..0858237 Binary files /dev/null and b/enhanced_exi_viewer.o differ diff --git a/exi_to_xml.c b/exi_to_xml.c deleted file mode 100644 index a54991a..0000000 --- a/exi_to_xml.c +++ /dev/null @@ -1,297 +0,0 @@ -#include -#include -#include - -/* EXI codec headers */ -#include "iso1EXIDatatypes.h" -#include "iso1EXIDatatypesDecoder.h" -#include "ByteStream.h" - -#define BUFFER_SIZE 4096 - -void print_xml_header() { - printf("\n"); - printf("\n"); -} - -void print_xml_footer() { - printf("\n"); -} - -void print_session_id_xml(uint8_t *bytes, size_t len) { - printf(" "); - for(size_t i = 0; i < len; i++) { - printf("%02X", bytes[i]); - } - printf("\n"); -} - -void print_iso1_xml(struct iso1EXIDocument *doc) { - if (!doc->V2G_Message_isUsed) return; - - print_xml_header(); - - // Header - printf("
\n"); - print_session_id_xml(doc->V2G_Message.Header.SessionID.bytes, - doc->V2G_Message.Header.SessionID.bytesLen); - - if (doc->V2G_Message.Header.Notification_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Header.Notification.FaultCode); - printf(" %s\n", doc->V2G_Message.Header.Notification.FaultMsg.characters); - printf(" \n"); - } - printf("
\n"); - - // Body - printf(" \n"); - - if (doc->V2G_Message.Body.SessionSetupReq_isUsed) { - printf(" \n"); - printf(" "); - for(size_t i = 0; i < doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i]); - } - printf("\n"); - printf(" \n"); - } - else if (doc->V2G_Message.Body.SessionSetupRes_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.SessionSetupRes.ResponseCode); - printf(" %s\n", doc->V2G_Message.Body.SessionSetupRes.EVSEID.characters); - if (doc->V2G_Message.Body.SessionSetupRes.EVSETimeStamp_isUsed) { - printf(" %ld\n", doc->V2G_Message.Body.SessionSetupRes.EVSETimeStamp); - } - printf(" \n"); - } - else if (doc->V2G_Message.Body.ServiceDiscoveryReq_isUsed) { - printf(" \n"); - } - else if (doc->V2G_Message.Body.ServiceDiscoveryRes_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.ServiceDiscoveryRes.ResponseCode); - printf(" \n"); - } - else if (doc->V2G_Message.Body.AuthorizationReq_isUsed) { - printf(" \n"); - if (doc->V2G_Message.Body.AuthorizationReq.Id_isUsed) { - printf(" %s\n", doc->V2G_Message.Body.AuthorizationReq.Id.characters); - } - if (doc->V2G_Message.Body.AuthorizationReq.GenChallenge_isUsed) { - printf(" "); - for(size_t i = 0; i < doc->V2G_Message.Body.AuthorizationReq.GenChallenge.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.AuthorizationReq.GenChallenge.bytes[i]); - } - printf("\n"); - } - printf(" \n"); - } - else if (doc->V2G_Message.Body.AuthorizationRes_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.AuthorizationRes.ResponseCode); - printf(" %d\n", doc->V2G_Message.Body.AuthorizationRes.EVSEProcessing); - printf(" \n"); - } - else if (doc->V2G_Message.Body.PreChargeReq_isUsed) { - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.PreChargeReq.EVTargetVoltage.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.PreChargeReq.EVTargetVoltage.Unit); - printf(" %d\n", doc->V2G_Message.Body.PreChargeReq.EVTargetVoltage.Value); - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.PreChargeReq.EVTargetCurrent.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.PreChargeReq.EVTargetCurrent.Unit); - printf(" %d\n", doc->V2G_Message.Body.PreChargeReq.EVTargetCurrent.Value); - printf(" \n"); - printf(" \n"); - } - else if (doc->V2G_Message.Body.PreChargeRes_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.PreChargeRes.ResponseCode); - printf(" \n"); - } - else if (doc->V2G_Message.Body.PowerDeliveryReq_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.PowerDeliveryReq.ChargeProgress); - printf(" %d\n", doc->V2G_Message.Body.PowerDeliveryReq.SAScheduleTupleID); - printf(" \n"); - } - else if (doc->V2G_Message.Body.PowerDeliveryRes_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.PowerDeliveryRes.ResponseCode); - printf(" \n"); - } - else if (doc->V2G_Message.Body.CurrentDemandReq_isUsed) { - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value); - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value); - printf(" \n"); - if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Value); - printf(" \n"); - } - if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Value); - printf(" \n"); - } - if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Value); - printf(" \n"); - } - printf(" \n"); - } - else if (doc->V2G_Message.Body.CurrentDemandRes_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.ResponseCode); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSENotification); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.NotificationMaxDelay); - if (doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus_isUsed) { - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus); - } - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEStatusCode); - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Value); - printf(" \n"); - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Value); - printf(" \n"); - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSECurrentLimitAchieved ? "true" : "false"); - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEVoltageLimitAchieved ? "true" : "false"); - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPowerLimitAchieved ? "true" : "false"); - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Value); - printf(" \n"); - } - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Value); - printf(" \n"); - } - if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Multiplier); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Unit); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Value); - printf(" \n"); - } - printf(" %.*s\n", - doc->V2G_Message.Body.CurrentDemandRes.EVSEID.charactersLen, - doc->V2G_Message.Body.CurrentDemandRes.EVSEID.characters); - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.SAScheduleTupleID); - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo_isUsed) { - printf(" \n"); - printf(" %.*s\n", - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterID.charactersLen, - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterID.characters); - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterReading_isUsed) { - printf(" %llu\n", - doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterReading); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading_isUsed) { - printf(" "); - for(int i = 0; i < doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.SigMeterReading.bytes[i]); - } - printf("\n"); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterStatus_isUsed) { - printf(" %d\n", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterStatus); - } - if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.TMeter_isUsed) { - printf(" %lld\n", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.TMeter); - } - printf(" \n"); - } - if (doc->V2G_Message.Body.CurrentDemandRes.ReceiptRequired_isUsed) { - printf(" %s\n", doc->V2G_Message.Body.CurrentDemandRes.ReceiptRequired ? "true" : "false"); - } - printf(" \n"); - } - else if (doc->V2G_Message.Body.SessionStopReq_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.SessionStopReq.ChargingSession); - printf(" \n"); - } - else if (doc->V2G_Message.Body.SessionStopRes_isUsed) { - printf(" \n"); - printf(" %d\n", doc->V2G_Message.Body.SessionStopRes.ResponseCode); - printf(" \n"); - } - else { - printf(" \n"); - } - - printf(" \n"); - print_xml_footer(); -} - -int main(int argc, char *argv[]) { - if (argc != 2) { - printf("Usage: %s input.exi\n", argv[0]); - printf("Converts EXI files to XML format\n"); - return -1; - } - - uint8_t buffer[BUFFER_SIZE]; - bitstream_t stream; - size_t pos = 0; - int errn = 0; - - struct iso1EXIDocument iso1Doc; - init_iso1EXIDocument(&iso1Doc); - - // Read file - errn = readBytesFromFile(argv[1], buffer, BUFFER_SIZE, &pos); - if (errn != 0) { - fprintf(stderr, "Error reading file: %s\n", argv[1]); - return -1; - } - - // Setup stream - pos = 0; // reset position for decoding - stream.size = BUFFER_SIZE; - stream.data = buffer; - stream.pos = &pos; - stream.buffer = 0; - stream.capacity = 0; - - // Try ISO1 decoder - errn = decode_iso1ExiDocument(&stream, &iso1Doc); - if (errn == 0) { - print_iso1_xml(&iso1Doc); - return 0; - } else { - fprintf(stderr, "Error: Could not decode EXI file (error: %d)\n", errn); - return -1; - } -} \ No newline at end of file diff --git a/exi_to_xml.exe b/exi_to_xml.exe deleted file mode 100644 index 1471779..0000000 Binary files a/exi_to_xml.exe and /dev/null differ diff --git a/exi_viewer.c b/exi_viewer.c deleted file mode 100644 index 5cae9d2..0000000 --- a/exi_viewer.c +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include -#include - -/* EXI codec headers */ -#include "iso1EXIDatatypes.h" -#include "iso1EXIDatatypesDecoder.h" -#include "iso2EXIDatatypes.h" -#include "iso2EXIDatatypesDecoder.h" -#include "dinEXIDatatypes.h" -#include "dinEXIDatatypesDecoder.h" -#include "ByteStream.h" - -#define BUFFER_SIZE 4096 - -void print_session_id(uint8_t *bytes, size_t len) { - printf("SessionID: "); - for(size_t i = 0; i < len; i++) { - printf("%02X", bytes[i]); - } - printf("\n"); -} - -void print_iso1_message(struct iso1EXIDocument *doc) { - printf("=== ISO1 V2G Message ===\n"); - - if (doc->V2G_Message_isUsed) { - // Print Header - printf("Header:\n"); - print_session_id(doc->V2G_Message.Header.SessionID.bytes, - doc->V2G_Message.Header.SessionID.bytesLen); - - if (doc->V2G_Message.Header.Notification_isUsed) { - printf("Notification: FaultCode=%d, FaultMsg=%s\n", - doc->V2G_Message.Header.Notification.FaultCode, - doc->V2G_Message.Header.Notification.FaultMsg.characters); - } - - // Print Body - printf("Body:\n"); - - if (doc->V2G_Message.Body.SessionSetupReq_isUsed) { - printf(" SessionSetupReq:\n"); - printf(" EVCCID: "); - for(size_t i = 0; i < doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytesLen; i++) { - printf("%c", doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i]); - } - printf("\n"); - } - - if (doc->V2G_Message.Body.SessionSetupRes_isUsed) { - printf(" SessionSetupRes:\n"); - printf(" ResponseCode: %d\n", doc->V2G_Message.Body.SessionSetupRes.ResponseCode); - printf(" EVSEID: %s\n", doc->V2G_Message.Body.SessionSetupRes.EVSEID.characters); - if (doc->V2G_Message.Body.SessionSetupRes.EVSETimeStamp_isUsed) { - printf(" EVSETimeStamp: %ld\n", doc->V2G_Message.Body.SessionSetupRes.EVSETimeStamp); - } - } - - if (doc->V2G_Message.Body.ServiceDiscoveryReq_isUsed) { - printf(" ServiceDiscoveryReq:\n"); - printf(" Service discovery request detected\n"); - } - - if (doc->V2G_Message.Body.AuthorizationReq_isUsed) { - printf(" AuthorizationReq:\n"); - if (doc->V2G_Message.Body.AuthorizationReq.Id_isUsed) { - printf(" ID: %s\n", doc->V2G_Message.Body.AuthorizationReq.Id.characters); - } - if (doc->V2G_Message.Body.AuthorizationReq.GenChallenge_isUsed) { - printf(" GenChallenge: "); - for(size_t i = 0; i < doc->V2G_Message.Body.AuthorizationReq.GenChallenge.bytesLen; i++) { - printf("%02X", doc->V2G_Message.Body.AuthorizationReq.GenChallenge.bytes[i]); - } - printf("\n"); - } - } - - if (doc->V2G_Message.Body.PowerDeliveryReq_isUsed) { - printf(" PowerDeliveryReq:\n"); - printf(" ChargeProgress: %d\n", doc->V2G_Message.Body.PowerDeliveryReq.ChargeProgress); - printf(" SAScheduleTupleID: %d\n", doc->V2G_Message.Body.PowerDeliveryReq.SAScheduleTupleID); - } - - if (doc->V2G_Message.Body.SessionStopReq_isUsed) { - printf(" SessionStopReq:\n"); - printf(" ChargingSession: %d\n", doc->V2G_Message.Body.SessionStopReq.ChargingSession); - } - - // Add more message types as needed - } - printf("\n"); -} - -void print_iso2_message(struct iso2EXIDocument *doc) { - printf("=== ISO2 V2G Message ===\n"); - - if (doc->V2G_Message_isUsed) { - printf("Header:\n"); - print_session_id(doc->V2G_Message.Header.SessionID.bytes, - doc->V2G_Message.Header.SessionID.bytesLen); - - printf("Body:\n"); - if (doc->V2G_Message.Body.SessionSetupReq_isUsed) { - printf(" SessionSetupReq:\n"); - printf(" EVCCID: "); - for(size_t i = 0; i < doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytesLen; i++) { - printf("%c", doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i]); - } - printf("\n"); - } - // Add more ISO2-specific message types as needed - } - printf("\n"); -} - -int main(int argc, char *argv[]) { - if (argc != 2) { - printf("Usage: %s input.exi\n", argv[0]); - printf("This tool decodes and displays the content of EXI files\n"); - return -1; - } - - uint8_t buffer[BUFFER_SIZE]; - bitstream_t stream; - size_t pos = 0; - int errn = 0; - - struct iso1EXIDocument iso1Doc; - struct iso2EXIDocument iso2Doc; - struct dinEXIDocument dinDoc; - - // Read file - errn = readBytesFromFile(argv[1], buffer, BUFFER_SIZE, &pos); - if (errn != 0) { - printf("Error reading file: %s\n", argv[1]); - return -1; - } - - printf("File: %s (%zu bytes)\n", argv[1], pos); - printf("Raw hex data: "); - for(size_t i = 0; i < (pos > 32 ? 32 : pos); i++) { - printf("%02X ", buffer[i]); - } - if (pos > 32) printf("..."); - printf("\n\n"); - - // Setup stream - pos = 0; // reset position for decoding - stream.size = BUFFER_SIZE; - stream.data = buffer; - stream.pos = &pos; - stream.buffer = 0; - stream.capacity = 0; - - // Try ISO1 first - pos = 0; - printf("Trying ISO1 decoder...\n"); - errn = decode_iso1ExiDocument(&stream, &iso1Doc); - if (errn == 0) { - printf("✓ Successfully decoded as ISO1\n"); - print_iso1_message(&iso1Doc); - return 0; - } else { - printf("✗ ISO1 decode failed (error: %d)\n", errn); - } - - // Try ISO2 - pos = 0; - printf("Trying ISO2 decoder...\n"); - errn = decode_iso2ExiDocument(&stream, &iso2Doc); - if (errn == 0) { - printf("✓ Successfully decoded as ISO2\n"); - print_iso2_message(&iso2Doc); - return 0; - } else { - printf("✗ ISO2 decode failed (error: %d)\n", errn); - } - - // Try DIN - pos = 0; - printf("Trying DIN decoder...\n"); - errn = decode_dinExiDocument(&stream, &dinDoc); - if (errn == 0) { - printf("✓ Successfully decoded as DIN\n"); - printf("=== DIN V2G Message ===\n"); - // Add DIN message printing as needed - return 0; - } else { - printf("✗ DIN decode failed (error: %d)\n", errn); - } - - printf("\n❌ Could not decode EXI file with any supported codec\n"); - printf("Supported formats: ISO1, ISO2, DIN\n"); - - return -1; -} \ No newline at end of file diff --git a/exi_viewer.exe b/exi_viewer.exe deleted file mode 100644 index 8dbf45a..0000000 Binary files a/exi_viewer.exe and /dev/null differ diff --git a/install/make-3.81.exe b/install/make-3.81.exe new file mode 100644 index 0000000..c8a8246 Binary files /dev/null and b/install/make-3.81.exe differ diff --git a/install/mingw-get-setup.exe b/install/mingw-get-setup.exe new file mode 100644 index 0000000..0b28bc1 Binary files /dev/null and b/install/mingw-get-setup.exe differ diff --git a/rawdata004.exi b/rawdata004.exi deleted file mode 100644 index 568bdb3..0000000 Binary files a/rawdata004.exi and /dev/null differ diff --git a/rawdata005.exi b/rawdata005.exi deleted file mode 100644 index 56abb57..0000000 Binary files a/rawdata005.exi and /dev/null differ diff --git a/rawdata006.exi b/rawdata006.exi deleted file mode 100644 index feefd16..0000000 Binary files a/rawdata006.exi and /dev/null differ diff --git a/test.exi b/test.exi deleted file mode 100644 index 3216fec..0000000 Binary files a/test.exi and /dev/null differ diff --git a/test.txt b/test.txt deleted file mode 100644 index de6db40..0000000 --- a/test.txt +++ /dev/null @@ -1 +0,0 @@ -8034282e23dd1022334455668660dd00000000002c06fffe80000000000000122233fffe445566fe80000000000000823428fffe2e23ddc365d121007d208c2ce1d2295018111c493a00000101fe8001000000001080980210509008c0c0c0e0c52110003200 diff --git a/test1.exi b/test1.exi deleted file mode 100644 index f113ec5..0000000 Binary files a/test1.exi and /dev/null differ diff --git a/test2.exi b/test2.exi deleted file mode 100644 index f113ec5..0000000 Binary files a/test2.exi and /dev/null differ diff --git a/test3.exi b/test3.exi deleted file mode 100644 index ea1e6a6..0000000 Binary files a/test3.exi and /dev/null differ diff --git a/test3.xml b/test3.xml deleted file mode 100644 index 1822937..0000000 --- a/test3.xml +++ /dev/null @@ -1,48 +0,0 @@ - - -
- 4142423030303831 -
- - - 0 - - 0 - 0 - 1 - 1 - - - 0 - 4 - 450 - - - 0 - 3 - 5 - - false - false - false - - 0 - 4 - 500 - - - 0 - 3 - 110 - - - 1 - 5 - 5000 - - Z - 1 - - -
diff --git a/test4_converted.exi b/test4_converted.exi new file mode 100644 index 0000000..7b82a14 --- /dev/null +++ b/test4_converted.exi @@ -0,0 +1 @@ +Error encoding to EXI (error: -109) diff --git a/test5.exi b/test5.exi new file mode 100644 index 0000000..0cacbcf Binary files /dev/null and b/test5.exi differ diff --git a/test5.xml b/test5.xml new file mode 100644 index 0000000..86a975e --- /dev/null +++ b/test5.xml @@ -0,0 +1,53 @@ + + +
+ 4142423030303831 +
+ + + + true + 0 + 100 + + + 0 + 3 + 1 + + + 0 + 4 + 460 + + + 0 + 4 + 471 + + + 0 + 3 + 100 + + + 3 + 5 + 50 + + false + true + + 0 + 2 + 0 + + + 0 + 2 + 0 + + + +
diff --git a/test5_final.exi b/test5_final.exi new file mode 100644 index 0000000..6c77723 --- /dev/null +++ b/test5_final.exi @@ -0,0 +1 @@ +P  P \ No newline at end of file diff --git a/test5_generated.exi b/test5_generated.exi new file mode 100644 index 0000000..ebbc024 --- /dev/null +++ b/test5_generated.exi @@ -0,0 +1,47 @@ +DEBUG: Parsing EVTargetCurrent section +DEBUG find_tag_in_section: Looking for 'Multiplier' in section of 137 chars +DEBUG: Found 'Multiplier' = '0' +DEBUG find_tag_in_section: Looking for 'Unit' in section of 137 chars +DEBUG: Found 'Unit' = '3' +DEBUG find_tag_in_section: Looking for 'Value' in section of 137 chars +DEBUG: Found 'Value' = '1' +DEBUG PhysicalValue: mult='0'->0, unit='3'->3, value='1'->1 +DEBUG: Parsing EVTargetVoltage section +DEBUG find_tag_in_section: Looking for 'Multiplier' in section of 139 chars +DEBUG: Found 'Multiplier' = '0' +DEBUG find_tag_in_section: Looking for 'Unit' in section of 139 chars +DEBUG: Found 'Unit' = '4' +DEBUG find_tag_in_section: Looking for 'Value' in section of 139 chars +DEBUG: Found 'Value' = '460' +DEBUG PhysicalValue: mult='0'->0, unit='4'->4, value='460'->460 +DEBUG find_tag_in_section: Looking for 'Multiplier' in section of 145 chars +DEBUG: Found 'Multiplier' = '0' +DEBUG find_tag_in_section: Looking for 'Unit' in section of 145 chars +DEBUG: Found 'Unit' = '4' +DEBUG find_tag_in_section: Looking for 'Value' in section of 145 chars +DEBUG: Found 'Value' = '471' +DEBUG PhysicalValue: mult='0'->0, unit='4'->4, value='471'->471 +DEBUG find_tag_in_section: Looking for 'Multiplier' in section of 145 chars +DEBUG: Found 'Multiplier' = '0' +DEBUG find_tag_in_section: Looking for 'Unit' in section of 145 chars +DEBUG: Found 'Unit' = '3' +DEBUG find_tag_in_section: Looking for 'Value' in section of 145 chars +DEBUG: Found 'Value' = '100' +DEBUG PhysicalValue: mult='0'->0, unit='3'->3, value='100'->100 +DEBUG find_tag_in_section: Looking for 'Multiplier' in section of 142 chars +DEBUG: Found 'Multiplier' = '3' +DEBUG find_tag_in_section: Looking for 'Unit' in section of 142 chars +DEBUG: Found 'Unit' = '5' +DEBUG find_tag_in_section: Looking for 'Value' in section of 142 chars +DEBUG: Found 'Value' = '50' +DEBUG PhysicalValue: mult='3'->3, unit='5'->5, value='50'->50 +DEBUG: Parsed V2G Message: + V2G_Message_isUsed: 1 + CurrentDemandReq_isUsed: 1 + EVReady: 1 + EVErrorCode: 0 + EVRESSSOC: 100 + EVTargetCurrent: 1 (Mult: 0, Unit: 3) + EVTargetVoltage: 460 (Mult: 0, Unit: 4) + ChargingComplete: 1 +P  P \ No newline at end of file diff --git a/test_message.exi b/test_message.exi deleted file mode 100644 index 7cf72a8..0000000 Binary files a/test_message.exi and /dev/null differ