#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; }