Unify enhanced_exi_viewer with Wireshark XML output and encoding support

- Remove unused XML output modes (ISO1, ISO2), keep only Wireshark-style output
- Integrate encoding functionality from enhanced_exi_viewer_simple
- Single executable now supports both encoding and decoding:
  * -decode: Convert EXI to Wireshark-style XML with ns1-4 prefixes
  * -encode: Convert XML to EXI format
  * default: Detailed EXI analysis mode
- Support for both standard XML tags and namespaced (ns3:) tags in encoding
- String conversion for units (A, V, W, s) and error codes (NO_ERROR)
- Compact XML output matching Wireshark format exactly
- Clean up old test files and separate tools

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-10 00:41:00 +09:00
parent 7edb3cde54
commit 5ed9b8cdcc
24 changed files with 717 additions and 1022 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

BIN
enhanced_exi_viewer.o Normal file

Binary file not shown.

View File

@@ -1,297 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* EXI codec headers */
#include "iso1EXIDatatypes.h"
#include "iso1EXIDatatypesDecoder.h"
#include "ByteStream.h"
#define BUFFER_SIZE 4096
void print_xml_header() {
printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
printf("<V2G_Message xmlns=\"urn:iso:15118:2:2013:MsgDef\"\n");
printf(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
}
void print_xml_footer() {
printf("</V2G_Message>\n");
}
void print_session_id_xml(uint8_t *bytes, size_t len) {
printf(" <SessionID>");
for(size_t i = 0; i < len; i++) {
printf("%02X", bytes[i]);
}
printf("</SessionID>\n");
}
void print_iso1_xml(struct iso1EXIDocument *doc) {
if (!doc->V2G_Message_isUsed) return;
print_xml_header();
// Header
printf(" <Header>\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(" <Notification>\n");
printf(" <FaultCode>%d</FaultCode>\n", doc->V2G_Message.Header.Notification.FaultCode);
printf(" <FaultMsg>%s</FaultMsg>\n", doc->V2G_Message.Header.Notification.FaultMsg.characters);
printf(" </Notification>\n");
}
printf(" </Header>\n");
// 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("%02X", doc->V2G_Message.Body.SessionSetupReq.EVCCID.bytes[i]);
}
printf("</EVCCID>\n");
printf(" </SessionSetupReq>\n");
}
else if (doc->V2G_Message.Body.SessionSetupRes_isUsed) {
printf(" <SessionSetupRes>\n");
printf(" <ResponseCode>%d</ResponseCode>\n", doc->V2G_Message.Body.SessionSetupRes.ResponseCode);
printf(" <EVSEID>%s</EVSEID>\n", doc->V2G_Message.Body.SessionSetupRes.EVSEID.characters);
if (doc->V2G_Message.Body.SessionSetupRes.EVSETimeStamp_isUsed) {
printf(" <EVSETimeStamp>%ld</EVSETimeStamp>\n", doc->V2G_Message.Body.SessionSetupRes.EVSETimeStamp);
}
printf(" </SessionSetupRes>\n");
}
else if (doc->V2G_Message.Body.ServiceDiscoveryReq_isUsed) {
printf(" <ServiceDiscoveryReq/>\n");
}
else if (doc->V2G_Message.Body.ServiceDiscoveryRes_isUsed) {
printf(" <ServiceDiscoveryRes>\n");
printf(" <ResponseCode>%d</ResponseCode>\n", doc->V2G_Message.Body.ServiceDiscoveryRes.ResponseCode);
printf(" </ServiceDiscoveryRes>\n");
}
else if (doc->V2G_Message.Body.AuthorizationReq_isUsed) {
printf(" <AuthorizationReq>\n");
if (doc->V2G_Message.Body.AuthorizationReq.Id_isUsed) {
printf(" <Id>%s</Id>\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("</GenChallenge>\n");
}
printf(" </AuthorizationReq>\n");
}
else if (doc->V2G_Message.Body.AuthorizationRes_isUsed) {
printf(" <AuthorizationRes>\n");
printf(" <ResponseCode>%d</ResponseCode>\n", doc->V2G_Message.Body.AuthorizationRes.ResponseCode);
printf(" <EVSEProcessing>%d</EVSEProcessing>\n", doc->V2G_Message.Body.AuthorizationRes.EVSEProcessing);
printf(" </AuthorizationRes>\n");
}
else if (doc->V2G_Message.Body.PreChargeReq_isUsed) {
printf(" <PreChargeReq>\n");
printf(" <EVTargetVoltage>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.PreChargeReq.EVTargetVoltage.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.PreChargeReq.EVTargetVoltage.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.PreChargeReq.EVTargetVoltage.Value);
printf(" </EVTargetVoltage>\n");
printf(" <EVTargetCurrent>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.PreChargeReq.EVTargetCurrent.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.PreChargeReq.EVTargetCurrent.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.PreChargeReq.EVTargetCurrent.Value);
printf(" </EVTargetCurrent>\n");
printf(" </PreChargeReq>\n");
}
else if (doc->V2G_Message.Body.PreChargeRes_isUsed) {
printf(" <PreChargeRes>\n");
printf(" <ResponseCode>%d</ResponseCode>\n", doc->V2G_Message.Body.PreChargeRes.ResponseCode);
printf(" </PreChargeRes>\n");
}
else if (doc->V2G_Message.Body.PowerDeliveryReq_isUsed) {
printf(" <PowerDeliveryReq>\n");
printf(" <ChargeProgress>%d</ChargeProgress>\n", doc->V2G_Message.Body.PowerDeliveryReq.ChargeProgress);
printf(" <SAScheduleTupleID>%d</SAScheduleTupleID>\n", doc->V2G_Message.Body.PowerDeliveryReq.SAScheduleTupleID);
printf(" </PowerDeliveryReq>\n");
}
else if (doc->V2G_Message.Body.PowerDeliveryRes_isUsed) {
printf(" <PowerDeliveryRes>\n");
printf(" <ResponseCode>%d</ResponseCode>\n", doc->V2G_Message.Body.PowerDeliveryRes.ResponseCode);
printf(" </PowerDeliveryRes>\n");
}
else if (doc->V2G_Message.Body.CurrentDemandReq_isUsed) {
printf(" <CurrentDemandReq>\n");
printf(" <EVTargetCurrent>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetCurrent.Value);
printf(" </EVTargetCurrent>\n");
printf(" <EVTargetVoltage>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandReq.EVTargetVoltage.Value);
printf(" </EVTargetVoltage>\n");
if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit_isUsed) {
printf(" <EVMaximumVoltageLimit>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumVoltageLimit.Value);
printf(" </EVMaximumVoltageLimit>\n");
}
if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit_isUsed) {
printf(" <EVMaximumCurrentLimit>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumCurrentLimit.Value);
printf(" </EVMaximumCurrentLimit>\n");
}
if (doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit_isUsed) {
printf(" <EVMaximumPowerLimit>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandReq.EVMaximumPowerLimit.Value);
printf(" </EVMaximumPowerLimit>\n");
}
printf(" </CurrentDemandReq>\n");
}
else if (doc->V2G_Message.Body.CurrentDemandRes_isUsed) {
printf(" <CurrentDemandRes>\n");
printf(" <ResponseCode>%d</ResponseCode>\n", doc->V2G_Message.Body.CurrentDemandRes.ResponseCode);
printf(" <DC_EVSEStatus>\n");
printf(" <EVSENotification>%d</EVSENotification>\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSENotification);
printf(" <NotificationMaxDelay>%d</NotificationMaxDelay>\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.NotificationMaxDelay);
if (doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus_isUsed) {
printf(" <EVSEIsolationStatus>%d</EVSEIsolationStatus>\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEIsolationStatus);
}
printf(" <EVSEStatusCode>%d</EVSEStatusCode>\n", doc->V2G_Message.Body.CurrentDemandRes.DC_EVSEStatus.EVSEStatusCode);
printf(" </DC_EVSEStatus>\n");
printf(" <EVSEPresentVoltage>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentVoltage.Value);
printf(" </EVSEPresentVoltage>\n");
printf(" <EVSEPresentCurrent>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPresentCurrent.Value);
printf(" </EVSEPresentCurrent>\n");
printf(" <EVSECurrentLimitAchieved>%s</EVSECurrentLimitAchieved>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSECurrentLimitAchieved ? "true" : "false");
printf(" <EVSEVoltageLimitAchieved>%s</EVSEVoltageLimitAchieved>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEVoltageLimitAchieved ? "true" : "false");
printf(" <EVSEPowerLimitAchieved>%s</EVSEPowerLimitAchieved>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEPowerLimitAchieved ? "true" : "false");
if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit_isUsed) {
printf(" <EVSEMaximumVoltageLimit>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumVoltageLimit.Value);
printf(" </EVSEMaximumVoltageLimit>\n");
}
if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit_isUsed) {
printf(" <EVSEMaximumCurrentLimit>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumCurrentLimit.Value);
printf(" </EVSEMaximumCurrentLimit>\n");
}
if (doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit_isUsed) {
printf(" <EVSEMaximumPowerLimit>\n");
printf(" <Multiplier>%d</Multiplier>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Multiplier);
printf(" <Unit>%d</Unit>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Unit);
printf(" <Value>%d</Value>\n", doc->V2G_Message.Body.CurrentDemandRes.EVSEMaximumPowerLimit.Value);
printf(" </EVSEMaximumPowerLimit>\n");
}
printf(" <EVSEID>%.*s</EVSEID>\n",
doc->V2G_Message.Body.CurrentDemandRes.EVSEID.charactersLen,
doc->V2G_Message.Body.CurrentDemandRes.EVSEID.characters);
printf(" <SAScheduleTupleID>%d</SAScheduleTupleID>\n", doc->V2G_Message.Body.CurrentDemandRes.SAScheduleTupleID);
if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo_isUsed) {
printf(" <MeterInfo>\n");
printf(" <MeterID>%.*s</MeterID>\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</MeterReading>\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("</SigMeterReading>\n");
}
if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterStatus_isUsed) {
printf(" <MeterStatus>%d</MeterStatus>\n", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.MeterStatus);
}
if (doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.TMeter_isUsed) {
printf(" <TMeter>%lld</TMeter>\n", doc->V2G_Message.Body.CurrentDemandRes.MeterInfo.TMeter);
}
printf(" </MeterInfo>\n");
}
if (doc->V2G_Message.Body.CurrentDemandRes.ReceiptRequired_isUsed) {
printf(" <ReceiptRequired>%s</ReceiptRequired>\n", doc->V2G_Message.Body.CurrentDemandRes.ReceiptRequired ? "true" : "false");
}
printf(" </CurrentDemandRes>\n");
}
else if (doc->V2G_Message.Body.SessionStopReq_isUsed) {
printf(" <SessionStopReq>\n");
printf(" <ChargingSession>%d</ChargingSession>\n", doc->V2G_Message.Body.SessionStopReq.ChargingSession);
printf(" </SessionStopReq>\n");
}
else if (doc->V2G_Message.Body.SessionStopRes_isUsed) {
printf(" <SessionStopRes>\n");
printf(" <ResponseCode>%d</ResponseCode>\n", doc->V2G_Message.Body.SessionStopRes.ResponseCode);
printf(" </SessionStopRes>\n");
}
else {
printf(" <!-- Unknown message type -->\n");
}
printf(" </Body>\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;
}
}

Binary file not shown.

View File

@@ -1,197 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 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;
}

Binary file not shown.

BIN
install/make-3.81.exe Normal file

Binary file not shown.

BIN
install/mingw-get-setup.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test.exi

Binary file not shown.

View File

@@ -1 +0,0 @@
8034282e23dd1022334455668660dd00000000002c06fffe80000000000000122233fffe445566fe80000000000000823428fffe2e23ddc365d121007d208c2ce1d2295018111c493a00000101fe8001000000001080980210509008c0c0c0e0c52110003200

BIN
test1.exi

Binary file not shown.

BIN
test2.exi

Binary file not shown.

BIN
test3.exi

Binary file not shown.

View File

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<V2G_Message xmlns="urn:iso:15118:2:2013:MsgDef"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<SessionID>4142423030303831</SessionID>
</Header>
<Body>
<CurrentDemandRes>
<ResponseCode>0</ResponseCode>
<DC_EVSEStatus>
<EVSENotification>0</EVSENotification>
<NotificationMaxDelay>0</NotificationMaxDelay>
<EVSEIsolationStatus>1</EVSEIsolationStatus>
<EVSEStatusCode>1</EVSEStatusCode>
</DC_EVSEStatus>
<EVSEPresentVoltage>
<Multiplier>0</Multiplier>
<Unit>4</Unit>
<Value>450</Value>
</EVSEPresentVoltage>
<EVSEPresentCurrent>
<Multiplier>0</Multiplier>
<Unit>3</Unit>
<Value>5</Value>
</EVSEPresentCurrent>
<EVSECurrentLimitAchieved>false</EVSECurrentLimitAchieved>
<EVSEVoltageLimitAchieved>false</EVSEVoltageLimitAchieved>
<EVSEPowerLimitAchieved>false</EVSEPowerLimitAchieved>
<EVSEMaximumVoltageLimit>
<Multiplier>0</Multiplier>
<Unit>4</Unit>
<Value>500</Value>
</EVSEMaximumVoltageLimit>
<EVSEMaximumCurrentLimit>
<Multiplier>0</Multiplier>
<Unit>3</Unit>
<Value>110</Value>
</EVSEMaximumCurrentLimit>
<EVSEMaximumPowerLimit>
<Multiplier>1</Multiplier>
<Unit>5</Unit>
<Value>5000</Value>
</EVSEMaximumPowerLimit>
<EVSEID>Z</EVSEID>
<SAScheduleTupleID>1</SAScheduleTupleID>
</CurrentDemandRes>
</Body>
</V2G_Message>

1
test4_converted.exi Normal file
View File

@@ -0,0 +1 @@
Error encoding to EXI (error: -109)

BIN
test5.exi Normal file

Binary file not shown.

53
test5.xml Normal file
View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<V2G_Message xmlns="urn:iso:15118:2:2013:MsgDef"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<SessionID>4142423030303831</SessionID>
</Header>
<Body>
<CurrentDemandReq>
<DC_EVStatus>
<EVReady>true</EVReady>
<EVErrorCode>0</EVErrorCode>
<EVRESSSOC>100</EVRESSSOC>
</DC_EVStatus>
<EVTargetCurrent>
<Multiplier>0</Multiplier>
<Unit>3</Unit>
<Value>1</Value>
</EVTargetCurrent>
<EVTargetVoltage>
<Multiplier>0</Multiplier>
<Unit>4</Unit>
<Value>460</Value>
</EVTargetVoltage>
<EVMaximumVoltageLimit>
<Multiplier>0</Multiplier>
<Unit>4</Unit>
<Value>471</Value>
</EVMaximumVoltageLimit>
<EVMaximumCurrentLimit>
<Multiplier>0</Multiplier>
<Unit>3</Unit>
<Value>100</Value>
</EVMaximumCurrentLimit>
<EVMaximumPowerLimit>
<Multiplier>3</Multiplier>
<Unit>5</Unit>
<Value>50</Value>
</EVMaximumPowerLimit>
<BulkChargingComplete>false</BulkChargingComplete>
<ChargingComplete>true</ChargingComplete>
<RemainingTimeToFullSoC>
<Multiplier>0</Multiplier>
<Unit>2</Unit>
<Value>0</Value>
</RemainingTimeToFullSoC>
<RemainingTimeToBulkSoC>
<Multiplier>0</Multiplier>
<Unit>2</Unit>
<Value>0</Value>
</RemainingTimeToBulkSoC>
</CurrentDemandReq>
</Body>
</V2G_Message>

1
test5_final.exi Normal file
View File

@@ -0,0 +1 @@
<EFBFBD><EFBFBD>P<><50>  P

47
test5_generated.exi Normal file
View File

@@ -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
<EFBFBD><EFBFBD>P<><50>  P

Binary file not shown.