EVerest / cbexigen

cbExiGen - The V2GTP EXI codec generator for cbV2G
Apache License 2.0
32 stars 18 forks source link

Encode/Decode "SalesTariff" messages #53

Closed gaohtao closed 10 months ago

gaohtao commented 11 months ago

I run OpenV2G Josev/iso15118 project, found that after the secc received ChargeParameterDiscoveryReq will launch (SalesTariff, SignedInfo) command code. This should be encoded using Fragment. In the cbexigen code, "struct iso2_exiFragment" lacks SalesTariff, can you add support?

secc trace: INFO 2023-11-07 09:48:29,714 - iso15118.shared.states (139): Entered state ChargeParameterDiscovery DEBUG 2023-11-07 09:48:29,714 - iso15118.shared.states (143): Waiting for up to 60.0 s INFO 2023-11-07 09:48:29,854 - iso15118.shared.exi_codec (299): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"55BC7135D086E839"},"Body":{"ChargeParameterDiscoveryReq":{"RequestedEnergyTransferMode":"AC_three_phase_core","AC_EVChargeParameter":{"DepartureTime":0,"EAmount":{"Multiplier":0,"Unit":"Wh","Value":60},"EVMaxVoltage":{"Multiplier":0,"Unit":"V","Value":400},"EVMaxCurrent":{"Multiplier":-3,"Unit":"A","Value":32000},"EVMinCurrent":{"Multiplier":0,"Unit":"A","Value":10}}}}}} INFO 2023-11-07 09:48:29,854 - iso15118.shared.comm_session (235): ChargeParameterDiscoveryReq received

INFO 2023-11-07 09:48:29,855 - iso15118.shared.exi_codec (245): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"SalesTariff": {"Id": "id1", "SalesTariffID": 10, "NumEPriceLevels": 1, "SalesTariffEntry": [{"EPriceLevel": 1, "RelativeTimeInterval": {"start": 0, "duration": 86400}}]}}

INFO 2023-11-07 09:48:29,934 - iso15118.shared.exi_codec (245): Message to encode (ns=http://www.w3.org/2000/09/xmldsig#): {"SignedInfo": {"CanonicalizationMethod": {"Algorithm": "http://www.w3.org/TR/canonical-exi/"}, "SignatureMethod": {"Algorithm": "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"}, "Reference": [{"Transforms": {"Transform": [{"Algorithm": "http://www.w3.org/TR/canonical-exi/"}]}, "DigestMethod": {"Algorithm": "http://www.w3.org/2001/04/xmlenc#sha256"}, "DigestValue": "ralwRkiB/uBn2TU6Q/IQq1ey1MVxvmK8cm/Rg2YmXT0=", "URI": "#id1"}]}}

INFO 2023-11-07 09:48:29,987 - iso15118.shared.exi_codec (245): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "55BC7135D086E839", "Signature": {"SignedInfo": {"CanonicalizationMethod": {"Algorithm": "http://www.w3.org/TR/canonical-exi/"}, "SignatureMethod": {"Algorithm": "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"}, "Reference": [{"Transforms": {"Transform": [{"Algorithm": "http://www.w3.org/TR/canonical-exi/"}]}, "DigestMethod": {"Algorithm": "http://www.w3.org/2001/04/xmlenc#sha256"}, "DigestValue": "ralwRkiB/uBn2TU6Q/IQq1ey1MVxvmK8cm/Rg2YmXT0=", "URI": "#id1"}]}, "SignatureValue": {"value": "MtCUZMoUm46ftk4s7hw39Hdq7uQoT5KJG5ITl0am0IJjqlnDqLX/zVhSPUsA/hN5tCcztOw7NIxExcbKA8H4TQ=="}}}, "Body": {"ChargeParameterDiscoveryRes": {"ResponseCode": "OK", "EVSEProcessing": "Finished", "SAScheduleList": {"SAScheduleTuple": [{"SAScheduleTupleID": 1, "PMaxSchedule": {"PMaxScheduleEntry": [{"PMax": {"Value": 11000, "Multiplier": 0, "Unit": "W"}, "RelativeTimeInterval": {"start": 0, "duration": 86400}}]}, "SalesTariff": {"Id": "id1", "SalesTariffID": 10, "NumEPriceLevels": 1, "SalesTariffEntry": [{"EPriceLevel": 1, "RelativeTimeInterval": {"start": 0, "duration": 86400}}]}}]}, "AC_EVSEChargeParameter": {"AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}, "EVSENominalVoltage": {"Value": 400, "Multiplier": 0, "Unit": "V"}, "EVSEMaxCurrent": {"Value": 32, "Multiplier": 0, "Unit": "A"}}}}}}

gaohtao commented 11 months ago

This is the encode result of Josev/iso15118:

 msgName= SalesTariff
   namespace= urn:iso:15118:2:2013:MsgDef
   json= {"SalesTariff": {"Id": "id1", "SalesTariffID": 10, "NumEPriceLevels": 2, "SalesTariffEntry": [{"EPriceLevel": 1, "RelativeTimeInterval": {"start": 0}}, {"EPriceLevel": 2, "RelativeTimeInterval": {"start": 1801, "duration": 1799}}]}}
encoded_message.length = 22
[ 0x80, 0xAE, 0x01, 0x5A, 0x59, 0x0C, 0x40, 0x92, 0x02, 0x00, 0x00, 0x80, 0x12, 0x04, 0x48, 0x70, 0x43, 0x87, 0x00, 0x08, 0xBE, 0x80, ]

This is the encode result of cbexigen by encode_iso2_SalesTariffType():
[80 AE 01 5A 59 0C 40 92 02 00 00 80 12 04 48 70 43 87 00 08 A0]

I notice that the last two bytes are different, please take care to verify and resolve the encode problem. It looks like an extra byte F4 was written after the encoding ended. such as: A0 10100000 BE 80 10111110 10000000 11110100 (F4)

barsnick commented 11 months ago

Hello,

I run OpenV2G Josev/iso15118 project

How did you integrate OpenV2G to Josev?

This should be encoded using Fragment. In the cbexigen code, "struct iso2_exiFragment" lacks SalesTariff, can you add support?

If you are missing elements to be fragment-encoded, you can add the coders by changing the configuration in src/config.py, variable iso2_fragments (assuming ISO 15118-2):

https://github.com/EVerest/cbexigen/blob/ae4f37e662d99860e4398386d2c62e411e7e432c/src/config.py#L80-L89

We made an initial assumption about which types need to be signed.

gaohtao commented 11 months ago

I added the print information in iso15118 project, output the exi encoding result, as follows:

INFO    2023-11-07 15:41:13,134 - iso15118.shared.comm_session (235): ChargeParameterDiscoveryReq received
INFO    2023-11-07 15:41:13,135 - iso15118.shared.exi_codec (245): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"SalesTariff": {"Id": "id1", "SalesTariffID": 10, "NumEPriceLevels": 1, "SalesTariffEntry": [{"EPriceLevel": 1, "RelativeTimeInterval": {"start": 0, "duration": 86400}}]}}
INFO    2023-11-07 15:41:13,185 - iso15118.shared.exificient_exi_codec (42): exi =
0x80 0xae 0x1 0x5a 0x59 0xc 0x40 0x92 0x1 0x0 0x0 0x20 0x28 0xc1 0x40 0x2 0x5f 0x40
INFO    2023-11-07 15:41:13,198 - iso15118.shared.exi_codec (245): Message to encode (ns=http://www.w3.org/2000/09/xmldsig#): {"SignedInfo": {"CanonicalizationMethod": {"Algorithm": "http://www.w3.org/TR/canonical-exi/"}, "SignatureMethod": {"Algorithm": "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"}, "Reference": [{"Transforms": {"Transform": [{"Algorithm": "http://www.w3.org/TR/canonical-exi/"}]}, "DigestMethod": {"Algorithm": "http://www.w3.org/2001/04/xmlenc#sha256"}, "DigestValue": "ralwRkiB/uBn2TU6Q/IQq1ey1MVxvmK8cm/Rg2YmXT0=", "URI": "#id1"}]}}
INFO    2023-11-07 15:41:13,245 - iso15118.shared.exificient_exi_codec (42): exi =
0x80 0x81 0x12 0xb4 0x3a 0x3a 0x38 0x1d 0x17 0x97 0xbb 0xbb 0xbb 0x97 0x3b 0x99 0x97 0x37 0xb9 0x33 0x97 0xaa 0x29 0x17 0xb1 0xb0 0xb7 0x37 0xb7 0x34 0xb1 0xb0 0xb6 0x16 0xb2 0xbc 0x34 0x97 0xa1 0xab 0x43 0xa3 0xa3 0x81 0xd1 0x79 0x7b 0xbb 0xbb 0xb9 0x73 0xb9 0x99 0x73 0x7b 0x93 0x39 0x79 0x91 0x81 0x81 0x89 0x79 0x81 0xa1 0x7b 0xc3 0x6b 0x63 0x23 0x9b 0x4b 0x39 0x6b 0x6b 0x7b 0x93 0x29 0x1b 0x2b 0x1b 0x23 0x9b 0x9 0x6b 0x9b 0x43 0x9 0x91 0xa9 0xb2 0x20 0x62 0x36 0x96 0x43 0x10 0x25 0x68 0x74 0x74 0x70 0x3a 0x2f 0x2f 0x77 0x77 0x77 0x2e 0x77 0x33 0x2e 0x6f 0x72 0x67 0x2f 0x54 0x52 0x2f 0x63 0x61 0x6e 0x6f 0x6e 0x69 0x63 0x61 0x6c 0x2d 0x65 0x78 0x69 0x2f 0x48 0x52 0xd0 0xe8 0xe8 0xe0 0x74 0x5e 0x5e 0xee 0xee 0xee 0x5c 0xee 0x66 0x5c 0xde 0xe4 0xce 0x5e 0x64 0x60 0x60 0x62 0x5e 0x60 0x68 0x5e 0xf0 0xda 0xd8 0xca 0xdc 0xc6 0x46 0xe6 0xd0 0xc2 0x64 0x6a 0x6c 0x84 0x15 0xb5 0x2e 0x8 0xc9 0x10 0x3f 0xdc 0xc 0xfb 0x26 0xa7 0x48 0x7e 0x42 0x15 0x6a 0xf6 0x5a 0x98 0xae 0x37 0xcc 0x57 0x8e 0x4d 0xfa 0x30 0x6c 0xc4 0xcb 0xa7 0xa3 0x70

This is the encode result of cbexigen by encode_iso2_SalesTariffType(): 0x80 0xae 0x1 0x5a 0x59 0xc 0x40 0x92 0x1 0x0 0x0 0x20 0x28 0xc1 0x40 0x2 0x50

The last two bytes are different, it looks like an extra byte F4 was written after the encoding ended. such as: 50 -- 01010000 5f 40 01011111 01000000 ------------1111 0100 (F4)

gaohtao commented 11 months ago

I change the configuration in src/config.py, variable iso2_fragments (assuming ISO 15118-2):

iso2_fragments = [
    'SignedInfo',
    'AuthorizationReq',
    'CertificateInstallationReq',
    'CertificateInstallationRes',
    'CertificateUpdateReq',
    'CertificateUpdateRes',
    'ChargeParameterDiscoveryRes',
    'MeteringReceiptReq',

    'ContractSignatureCertChain',
    'ContractSignatureEncryptedPrivateKey',
    'DHpublickey',
    'eMAID',
    'SalesTariff'
]

Then I got the code as following:

// elements of EXI fragment
struct iso2_exiFragment {
    union {
        struct iso2_AuthorizationReqType AuthorizationReq;
        struct iso2_CertificateInstallationReqType CertificateInstallationReq;
        struct iso2_CertificateInstallationResType CertificateInstallationRes;
        struct iso2_CertificateUpdateReqType CertificateUpdateReq;
        struct iso2_CertificateUpdateResType CertificateUpdateRes;
        struct iso2_ChargeParameterDiscoveryResType ChargeParameterDiscoveryRes;
        struct iso2_CertificateChainType ContractSignatureCertChain;
        struct iso2_ContractSignatureEncryptedPrivateKeyType ContractSignatureEncryptedPrivateKey;
        struct iso2_DiffieHellmanPublickeyType DHpublickey;
        struct iso2_MeteringReceiptReqType MeteringReceiptReq;
        struct iso2_SalesTariffType SalesTariff;
        struct iso2_SignedInfoType SignedInfo;
        struct iso2_EMAIDType eMAID;
    };
    unsigned int AuthorizationReq_isUsed:1;
    unsigned int CertificateInstallationReq_isUsed:1;
    unsigned int CertificateInstallationRes_isUsed:1;
    unsigned int CertificateUpdateReq_isUsed:1;
    unsigned int CertificateUpdateRes_isUsed:1;
    unsigned int ChargeParameterDiscoveryRes_isUsed:1;
    unsigned int ContractSignatureCertChain_isUsed:1;
    unsigned int ContractSignatureEncryptedPrivateKey_isUsed:1;
    unsigned int DHpublickey_isUsed:1;
    unsigned int MeteringReceiptReq_isUsed:1;
    unsigned int SalesTariff_isUsed:1;
    unsigned int SignedInfo_isUsed:1;
    unsigned int eMAID_isUsed:1;
};

So, it works right.

barsnick commented 11 months ago

Regarding the missing types: Are you experimenting, or do you really need to fragment-code these additional types?

Glad that you got the additional types to work. Yet we assume that the code will not compile, because there exists e.g. no encode_iso2_eMAIDType(). We haven't included any simple types in the fragment coders (yet), as seen by the comment in src/config.py.

barsnick commented 11 months ago

Regarding the extra (or missing) bytes in the fragment encoder and decoder: This seems to be an oversight on our side. We need to add these bytes, otherwise the validation of the fragment by other decoders will not work. (We can decode both of your posted variants, because we fail to check for the extra bytes in our decoder.)

We will look at these issues and fix them.

gaohtao commented 11 months ago

1) Don't warry, We already have encode_iso2_EMAIDType() in the code "iso2_msgDefEncoder.c". 2) Very good, you already know the specific coding problem of extra byte, I am looking forward to your fix.

barsnick commented 10 months ago

Hi @gaohtao, the fixes have been merged into branch main. Please be so kind to test them.