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