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:
File diff suppressed because it is too large
Load Diff
Binary file not shown.
BIN
enhanced_exi_viewer.o
Normal file
BIN
enhanced_exi_viewer.o
Normal file
Binary file not shown.
297
exi_to_xml.c
297
exi_to_xml.c
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
exi_to_xml.exe
BIN
exi_to_xml.exe
Binary file not shown.
197
exi_viewer.c
197
exi_viewer.c
@@ -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;
|
|
||||||
}
|
|
||||||
BIN
exi_viewer.exe
BIN
exi_viewer.exe
Binary file not shown.
BIN
install/make-3.81.exe
Normal file
BIN
install/make-3.81.exe
Normal file
Binary file not shown.
BIN
install/mingw-get-setup.exe
Normal file
BIN
install/mingw-get-setup.exe
Normal file
Binary file not shown.
BIN
rawdata004.exi
BIN
rawdata004.exi
Binary file not shown.
BIN
rawdata005.exi
BIN
rawdata005.exi
Binary file not shown.
BIN
rawdata006.exi
BIN
rawdata006.exi
Binary file not shown.
1
test.txt
1
test.txt
@@ -1 +0,0 @@
|
|||||||
8034282e23dd1022334455668660dd00000000002c06fffe80000000000000122233fffe445566fe80000000000000823428fffe2e23ddc365d121007d208c2ce1d2295018111c493a00000101fe8001000000001080980210509008c0c0c0e0c52110003200
|
|
||||||
48
test3.xml
48
test3.xml
@@ -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
1
test4_converted.exi
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Error encoding to EXI (error: -109)
|
||||||
53
test5.xml
Normal file
53
test5.xml
Normal 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
1
test5_final.exi
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>P<><50>P
|
||||||
47
test5_generated.exi
Normal file
47
test5_generated.exi
Normal 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
|
||||||
BIN
test_message.exi
BIN
test_message.exi
Binary file not shown.
Reference in New Issue
Block a user