feat: Implement Phase 3 Extended Features in C - Payment, Charging Status, Session Stop
- Add function declarations for all 6 Phase 3 message handlers - Add message detection logic for: - PaymentServiceSelectionReq/Res: Payment method selection - ChargingStatusReq/Res: AC charging status monitoring - SessionStopReq/Res: Session termination control - Implement comprehensive helper functions with: - Payment option analysis (Contract vs External) - Service list parsing and display - AC charging status with meter information - Session termination with ChargingSession enum handling - Fix struct member access for iso1SessionStopReqType.ChargingSession - Include emoji indicators for better UX and debugging - Phase 3 C implementation complete, ready for VC2022/dotnet ports 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
207
V2GDecoder.c
207
V2GDecoder.c
@@ -41,6 +41,14 @@ void print_authorization_res_details(struct iso1AuthorizationResType *authorizat
|
||||
void print_charge_param_discovery_req_details(struct iso1ChargeParameterDiscoveryReqType *chargeParamReq);
|
||||
void print_charge_param_discovery_res_details(struct iso1ChargeParameterDiscoveryResType *chargeParamRes);
|
||||
|
||||
// Phase 3: Extended Features - Function declarations
|
||||
void print_payment_service_selection_req_details(struct iso1PaymentServiceSelectionReqType *paymentServiceSelectionReq);
|
||||
void print_payment_service_selection_res_details(struct iso1PaymentServiceSelectionResType *paymentServiceSelectionRes);
|
||||
void print_charging_status_req_details(struct iso1ChargingStatusReqType *chargingStatusReq);
|
||||
void print_charging_status_res_details(struct iso1ChargingStatusResType *chargingStatusRes);
|
||||
void print_session_stop_req_details(struct iso1SessionStopReqType *sessionStopReq);
|
||||
void print_session_stop_res_details(struct iso1SessionStopResType *sessionStopRes);
|
||||
|
||||
// Function to detect and extract EXI body from V2G Transfer Protocol data
|
||||
size_t extract_exi_body(uint8_t* input_data, size_t input_size, uint8_t* output_data, size_t output_size) {
|
||||
if (input_size < 8) {
|
||||
@@ -1059,6 +1067,31 @@ void print_iso1_message(struct iso1EXIDocument* doc) {
|
||||
printf("✅ ChargeParameterDiscoveryRes: Charge parameter response\n");
|
||||
print_charge_param_discovery_res_details(&doc->V2G_Message.Body.ChargeParameterDiscoveryRes);
|
||||
}
|
||||
// Phase 3: Extended Features - Message detection
|
||||
else if (doc->V2G_Message.Body.PaymentServiceSelectionReq_isUsed) {
|
||||
printf("💳 PaymentServiceSelectionReq: Payment method selection request\n");
|
||||
print_payment_service_selection_req_details(&doc->V2G_Message.Body.PaymentServiceSelectionReq);
|
||||
}
|
||||
else if (doc->V2G_Message.Body.PaymentServiceSelectionRes_isUsed) {
|
||||
printf("💳 PaymentServiceSelectionRes: Payment method selection response\n");
|
||||
print_payment_service_selection_res_details(&doc->V2G_Message.Body.PaymentServiceSelectionRes);
|
||||
}
|
||||
else if (doc->V2G_Message.Body.ChargingStatusReq_isUsed) {
|
||||
printf("🔋 ChargingStatusReq: AC charging status request\n");
|
||||
print_charging_status_req_details(&doc->V2G_Message.Body.ChargingStatusReq);
|
||||
}
|
||||
else if (doc->V2G_Message.Body.ChargingStatusRes_isUsed) {
|
||||
printf("🔋 ChargingStatusRes: AC charging status response\n");
|
||||
print_charging_status_res_details(&doc->V2G_Message.Body.ChargingStatusRes);
|
||||
}
|
||||
else if (doc->V2G_Message.Body.SessionStopReq_isUsed) {
|
||||
printf("🛑 SessionStopReq: Session termination request\n");
|
||||
print_session_stop_req_details(&doc->V2G_Message.Body.SessionStopReq);
|
||||
}
|
||||
else if (doc->V2G_Message.Body.SessionStopRes_isUsed) {
|
||||
printf("🛑 SessionStopRes: Session termination response\n");
|
||||
print_session_stop_res_details(&doc->V2G_Message.Body.SessionStopRes);
|
||||
}
|
||||
else if (doc->V2G_Message.Body.CurrentDemandReq_isUsed) {
|
||||
printf("Message Type: CurrentDemandReq\n");
|
||||
|
||||
@@ -1600,3 +1633,177 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Phase 3: Extended Features - Helper function implementations
|
||||
|
||||
void print_payment_service_selection_req_details(struct iso1PaymentServiceSelectionReqType *paymentServiceSelectionReq) {
|
||||
printf(" 📄 Payment Service Selection Request Details:\\n");
|
||||
printf(" 💳 Purpose: Select payment method for charging session\\n");
|
||||
|
||||
printf(" 🆔 Selected Payment Option: ");
|
||||
switch(paymentServiceSelectionReq->SelectedPaymentOption) {
|
||||
case iso1paymentOptionType_Contract:
|
||||
printf("Contract-based payment\\n");
|
||||
break;
|
||||
case iso1paymentOptionType_ExternalPayment:
|
||||
printf("External payment method\\n");
|
||||
break;
|
||||
default:
|
||||
printf("Unknown (%d)\\n", paymentServiceSelectionReq->SelectedPaymentOption);
|
||||
}
|
||||
|
||||
printf(" 📋 Selected Service List:\\n");
|
||||
if (paymentServiceSelectionReq->SelectedServiceList.SelectedService.arrayLen > 0) {
|
||||
for (int i = 0; i < paymentServiceSelectionReq->SelectedServiceList.SelectedService.arrayLen; i++) {
|
||||
printf(" %d. Service ID: %d, Parameter Set ID: %d\\n",
|
||||
i + 1,
|
||||
paymentServiceSelectionReq->SelectedServiceList.SelectedService.array[i].ServiceID,
|
||||
paymentServiceSelectionReq->SelectedServiceList.SelectedService.array[i].ParameterSetID_isUsed ?
|
||||
paymentServiceSelectionReq->SelectedServiceList.SelectedService.array[i].ParameterSetID : -1);
|
||||
}
|
||||
} else {
|
||||
printf(" No services selected\\n");
|
||||
}
|
||||
|
||||
printf(" ✅ Payment service selection requested\\n");
|
||||
}
|
||||
|
||||
void print_payment_service_selection_res_details(struct iso1PaymentServiceSelectionResType *paymentServiceSelectionRes) {
|
||||
printf(" 📄 Payment Service Selection Response Details:\\n");
|
||||
printf(" 💳 Purpose: Confirm payment method selection\\n");
|
||||
|
||||
printf(" 📊 Response Code: ");
|
||||
switch(paymentServiceSelectionRes->ResponseCode) {
|
||||
case iso1responseCodeType_OK:
|
||||
printf("✅ OK - Payment selection accepted\\n");
|
||||
break;
|
||||
case iso1responseCodeType_OK_NewSessionEstablished:
|
||||
printf("✅ OK - New session established\\n");
|
||||
break;
|
||||
case iso1responseCodeType_FAILED:
|
||||
printf("❌ FAILED\\n");
|
||||
break;
|
||||
default:
|
||||
printf("⚠️ Unknown (%d)\\n", paymentServiceSelectionRes->ResponseCode);
|
||||
}
|
||||
|
||||
printf(" 🔄 Payment method selection completed\\n");
|
||||
}
|
||||
|
||||
void print_charging_status_req_details(struct iso1ChargingStatusReqType *chargingStatusReq) {
|
||||
printf(" 📄 Charging Status Request Details:\\n");
|
||||
printf(" 🔋 Purpose: Request AC charging status information\\n");
|
||||
|
||||
printf(" 🔍 Requesting current charging status from EVSE\\n");
|
||||
printf(" 📊 Status inquiry for AC charging session\\n");
|
||||
}
|
||||
|
||||
void print_charging_status_res_details(struct iso1ChargingStatusResType *chargingStatusRes) {
|
||||
printf(" 📄 Charging Status Response Details:\\n");
|
||||
printf(" 🔋 Purpose: Provide AC charging status information\\n");
|
||||
|
||||
printf(" 📊 Response Code: ");
|
||||
switch(chargingStatusRes->ResponseCode) {
|
||||
case iso1responseCodeType_OK:
|
||||
printf("✅ OK\\n");
|
||||
break;
|
||||
case iso1responseCodeType_OK_NewSessionEstablished:
|
||||
printf("✅ OK - New session established\\n");
|
||||
break;
|
||||
case iso1responseCodeType_FAILED:
|
||||
printf("❌ FAILED\\n");
|
||||
break;
|
||||
default:
|
||||
printf("⚠️ Unknown (%d)\\n", chargingStatusRes->ResponseCode);
|
||||
}
|
||||
|
||||
printf(" 🆔 EVSE ID: ");
|
||||
if (chargingStatusRes->EVSEID.charactersLen > 0) {
|
||||
printf("%.*s\\n", (int)chargingStatusRes->EVSEID.charactersLen, chargingStatusRes->EVSEID.characters);
|
||||
} else {
|
||||
printf("Not provided\\n");
|
||||
}
|
||||
|
||||
printf(" 🔌 SA Schedule Tuple ID: %d\\n", chargingStatusRes->SAScheduleTupleID);
|
||||
|
||||
if (chargingStatusRes->EVSEMaxCurrent_isUsed) {
|
||||
printf(" ⚡ EVSE Max Current: %d %s (10^%d)\\n",
|
||||
chargingStatusRes->EVSEMaxCurrent.Value,
|
||||
chargingStatusRes->EVSEMaxCurrent.Unit == 5 ? "A" : "Unknown Unit",
|
||||
chargingStatusRes->EVSEMaxCurrent.Multiplier);
|
||||
}
|
||||
|
||||
if (chargingStatusRes->MeterInfo_isUsed) {
|
||||
printf(" 📊 Meter Information:\\n");
|
||||
printf(" 🆔 Meter ID: ");
|
||||
if (chargingStatusRes->MeterInfo.MeterID.charactersLen > 0) {
|
||||
printf("%.*s\\n", (int)chargingStatusRes->MeterInfo.MeterID.charactersLen,
|
||||
chargingStatusRes->MeterInfo.MeterID.characters);
|
||||
} else {
|
||||
printf("Not provided\\n");
|
||||
}
|
||||
|
||||
if (chargingStatusRes->MeterInfo.MeterReading_isUsed) {
|
||||
printf(" 📏 Meter Reading: %llu Wh\\n",
|
||||
(unsigned long long)chargingStatusRes->MeterInfo.MeterReading);
|
||||
}
|
||||
|
||||
if (chargingStatusRes->MeterInfo.SigMeterReading_isUsed) {
|
||||
printf(" 🔏 Signed Meter Reading: %.*s\\n",
|
||||
(int)chargingStatusRes->MeterInfo.SigMeterReading.bytesLen,
|
||||
(char*)chargingStatusRes->MeterInfo.SigMeterReading.bytes);
|
||||
}
|
||||
|
||||
if (chargingStatusRes->MeterInfo.MeterStatus_isUsed) {
|
||||
printf(" 📊 Meter Status: %d\\n", chargingStatusRes->MeterInfo.MeterStatus);
|
||||
}
|
||||
}
|
||||
|
||||
if (chargingStatusRes->ReceiptRequired_isUsed) {
|
||||
printf(" 🧾 Receipt Required: %s\\n",
|
||||
chargingStatusRes->ReceiptRequired ? "Yes" : "No");
|
||||
}
|
||||
|
||||
printf(" ✅ AC charging status provided\\n");
|
||||
}
|
||||
|
||||
void print_session_stop_req_details(struct iso1SessionStopReqType *sessionStopReq) {
|
||||
printf(" 📄 Session Stop Request Details:\\n");
|
||||
printf(" 🛑 Purpose: Request charging session termination\\n");
|
||||
|
||||
printf(" 🔄 Charging Session: ");
|
||||
switch(sessionStopReq->ChargingSession) {
|
||||
case iso1chargingSessionType_Terminate:
|
||||
printf("✅ Terminate - Session ending completely\\n");
|
||||
break;
|
||||
case iso1chargingSessionType_Pause:
|
||||
printf("⏸️ Pause - Session paused temporarily\\n");
|
||||
break;
|
||||
default:
|
||||
printf("⚠️ Unknown (%d)\\n", sessionStopReq->ChargingSession);
|
||||
}
|
||||
|
||||
printf(" 🛑 Requesting session termination\\n");
|
||||
}
|
||||
|
||||
void print_session_stop_res_details(struct iso1SessionStopResType *sessionStopRes) {
|
||||
printf(" 📄 Session Stop Response Details:\\n");
|
||||
printf(" 🛑 Purpose: Confirm charging session termination\\n");
|
||||
|
||||
printf(" 📊 Response Code: ");
|
||||
switch(sessionStopRes->ResponseCode) {
|
||||
case iso1responseCodeType_OK:
|
||||
printf("✅ OK - Session terminated successfully\\n");
|
||||
break;
|
||||
case iso1responseCodeType_OK_NewSessionEstablished:
|
||||
printf("✅ OK - New session established\\n");
|
||||
break;
|
||||
case iso1responseCodeType_FAILED:
|
||||
printf("❌ FAILED - Session termination failed\\n");
|
||||
break;
|
||||
default:
|
||||
printf("⚠️ Unknown (%d)\\n", sessionStopRes->ResponseCode);
|
||||
}
|
||||
|
||||
printf(" 🔚 Charging session terminated\\n");
|
||||
}
|
||||
Reference in New Issue
Block a user