Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support of ISO 15118 to read car SOC #25

Open
abstractionnl opened this issue Jul 26, 2022 · 187 comments
Open

Support of ISO 15118 to read car SOC #25

abstractionnl opened this issue Jul 26, 2022 · 187 comments

Comments

@abstractionnl
Copy link

At some public chargers (particularly ones by Alfen), the car can communicate with the charging station to give details about it's SOC, this is shown on the charger display. Looking around the internet this is done with the ISO 15118 standard. Having the SOC would allow some new smart additions:

  • Stop charging when battery reaches a certain % (to prevent battery degradation)
  • Switch to solar mode when battery reaches a certain % (always have enough available for small rides and only trickle in more on solar when available)
  • Charge just in time by setting a goal percentage to be available at a certain date/time, and wait for solar in the meantime.
@mstegen
Copy link
Member

mstegen commented Jul 27, 2022

I just heard about this a few days ago. These chargers talk to the car behaving like a DC charger, over ISO 15118 you can indeed request the SOC and other parameters of the EV.
After receiving this information they then basically tell the EV, oh sorry i'm not capable of delivering DC, and start charging in normal AC mode.
If you stop the charge at regular intervals, and then start the sequence again, you can predict when the EV is fully charged.

The SmartEVSE v3 does not have a ISO 15118 modem. So its not possible to request this information.

@abstractionnl
Copy link
Author

It looks like it is using powerline communication, over the CP wire. An external modem would be needed, but I see none available over the shelf.

@fluppie
Copy link

fluppie commented Jul 29, 2022

See this paper: https://ltu.diva-portal.org/smash/get/diva2:1546405/FULLTEXT01.pdf
Or with this Qualcomm chip: https://www.qualcomm.com/products/application/automotive/auto-connectivity/qca7006aq

A workaround for the current SmartEVSE is integration with https://evcc.io to get SoC via BMW Connected Drive, MyAudi, Volvo on Call etc.
https://docs.evcc.io/docs/devices/vehicles

@martijndierckx
Copy link

martijndierckx commented Aug 4, 2022

SmartEVSE v4? :-)

Just noticed the same at a Tesla Supercharger, charging my non-tesla. Also wondering: “If Tesla can read that data, then SmartEVSE should also be able to do it … right?”

@mstegen
Copy link
Member

mstegen commented Aug 4, 2022

Ha!
I'll see if i can order some pre-made modules with a Qualcomm chip. I found some from 8devices and chargebyte/intech.

@Fixh1
Copy link

Fixh1 commented Sep 27, 2022

I added an MQTT task to the SmartEVSE (and installed Mosquitto, Node Red etc) And via Node Red I can get all information from my Zoë, including the SOC. So I can forward that information to the SmartEVSE. Not using it yet, but the option is there.
I only have a problem with the disconnecting Wifi :-(.

@fluppie
Copy link

fluppie commented Sep 27, 2022

Yeah sure, but that's not always working well. Like BMW's connected drive that from time to time doesn't work for 1-2 days. The advantage of the qualcomm chip is it can always read SoC. Ideal for cars in an underground parking lot without wifi.

@martijndierckx
Copy link

I noticed the same with Porsche's service. Not very reliable, plus on many occasions with delays.
So a direct integration would be much much better.

@dingo35
Copy link
Collaborator

dingo35 commented Dec 23, 2022

Ha!
I'll see if i can order some pre-made modules with a Qualcomm chip. I found some from 8devices and chargebyte/intech.

@mstegen Not sure what the status is, but I would be happy to help develop the firmware adaptions for this; I am one of the developers of the serkri distribution, but it would make no sense doing that work twice....

@fluppie
Copy link

fluppie commented Jan 24, 2023

@mstegen are you (still) looking into this for v4?

@mstegen
Copy link
Member

mstegen commented Jan 27, 2023

Thanks for the reminder, just ordered some red/yellow beet-e modules to play with.

@martijndierckx
Copy link

@mstegen any luck on testing the beet-e?

@mstegen
Copy link
Member

mstegen commented Feb 22, 2023

I received the modules (Red beet/ Yellow beet and Red beet carrier board), but had no time yet to look into it.

@arpiecodes
Copy link
Contributor

arpiecodes commented Mar 3, 2023

I am also actively looking for something that could 1. provide me with a SoC on the car and 2. authenticate the car without having to use a RFID card/manual action. It seems ISO15118 is the way to go forward.

I also stumbled across the web already in my quest. One thing that was very enlightening was this; https://github.com/uhi22/pyPLC#example-flow. I also came across Python libraries supporting both SLAC (link negotiation) and the actual ISO15118 communications. It all looks pretty expansive, but very cool! I mean come on, talking over IP with your car, that's awesome!

I am not sure if implementation directly inside SmartEVSE is a good idea, though. It would most likely be possible, but full integration (including the Plug&Charge stuff) would require quite a big list of 'extras', like TLS, full IPv6 stack, dynamically spawning UDP+TCP servers for communication, etc. It sounds like a lot to handle for the/a ESP32.

With that in mind, I'd like to try to add ISO15118 through a separate component (e.g. Raspberry Pi) that could act as a charge-controller-controller, handling the actual powerline communication with the car and 'work together' with the SmartEVSE to control the contactor, as the basic communication over the CP/PE lines (monitoring the EVSE 'states') is still required as part of that communication flow/charging process. I was thinking of using MQTT for this, but I guess a simple/small API or even ModBus would work as well.

I do hope the control signalling on the CP line (e.g. load balancing) and the PLC communication are not mutually exclusive, and can be combined; else above may not work out the way I am envisioning.. But we can at least try!

I have sent a mail to the people over at CODICO to find out if that carrier board they have listed on their site containing the RED BEET (https://www.codico.com/de/red-carrier-board-e-1-1-evse) would be plug&play and allow me to get a head start. If it's what I need to get going quickly, I'll order one and see what I can find out.

@ArendJanKramer
Copy link
Contributor

@arpiecodes I'm pretty interested in what CODICO has to say. Thanks for the link though, I hadn't spot the carrier boards before.
I ordered one, will update you all. Like you said, pretty awesome to talk over IP with the car.
I have also seen this one: https://www.codico.com/en/powerline-gp-evse-din-rail-modul-version-1-1
But holy smokes, that's not cheap for DIY.

My first plan is to setup a Raspberry PI with the board, and see if we can get some form of communication. Things I'm interested in are:

  • First of learning more about this topic, I'm a blank slate
  • Read car information, perhaps useful for authorization purposes
  • Read SoC and other information.

I also looked at the carrier board with a white beet instead, which has an ST32 microcontroller. However, if I understood correctly the sample code needs to be licensed, and I couldn't find sample code online.
Otherwise, I'd like to have experimented with that instead.

Once this all works, we could make a PCB with small microcontroller and a RED beet that acts as a modbus slave for SmartEVSE to supply information about car SoC. (or SmartEVSE v4)

One thing I'm interested in to learn is how we deal with CP signal, as it is currently controlled by SmartEVSE, while pyPLC mentions that the PWM needs to be set to 5% duty cycle for a while to setup digital communication. Well, we'll see once the board arrives and things need to be wired. I usually learn these things from doing it wrong initially.

@arpiecodes
Copy link
Contributor

arpiecodes commented Mar 9, 2023

@ArendJanKramer good to hear you took the jump and simply bought one. Maybe I should do the same. I have no reaction from Werner from CODICO yet. I am unsure if they even respond to hobby users like me. :-) If I hear anything back, will let you know.

Your plan sounds nice. However, as far as I understood the beet modules only contain the components to establish the physical connection/do signal conversion. The QCA7xxx chip on-board is connected through SPI to something else. And on this something else you will have to run the full networking stack (IPv6, SLAC, UDP/TCP servers, etc.). I don't think this will be possible on a PIC as it's all pretty high level stuff. Maybe you could get it to work reliably on a dedicated ESP32 though. AFAIK it has everything on-board to do these things.

Using modbus to talk with the EVSE is a nice solution. Do have to consider the SmartEVSE will remain master in this case. So it will continually have to poll the module in such case, while also making sure your module gets the CP line state updated every now and then.

@dingo35
Copy link
Collaborator

dingo35 commented Mar 9, 2023

Since the SmartEVSE already controls the CP line, and already has a full tcp server running (e.g. serkri distribution), IMHO it would make most sense to connect the modem through the existing SPI interface on the SmartEVSE board, and do all low-level communication on the ESP32; it might be necessary to offload the tls and complicated encryption/decryption routines that are involved with ISO15118 to a raspberry pi, but doing ipv6 is already possible since 2019 so that shouldnt be a problem...
Also if the encryption/decryption logic is in the hardware of the modem (which seems to be the case for some of the beet-kits) you wouldnt need to offload at all...

@arpiecodes
Copy link
Contributor

Running the serkri distribution sometimes already shows slowdowns when interacting with it through REST (at least, in my case) while not doing much with it, really. I'd not like my charge controller to end up being busy with a lot of extra stuff jammed into it to the extend of that potentially causing issues with the core functionality/compromising it. It would also raise complexity even further.

Besides, we would still need a way to react to stuff like 'identifying' the car, send through SoC and be able to control it from (for example) HA. The official repo doesn't support this as of this moment either.

I'd much rather see something like this added to Sensorbox v3 (and have that assume the master modbus device role, also run the REST API and MQTT client for example) vs. trying to cram it all into one device.

@dingo35
Copy link
Collaborator

dingo35 commented Mar 9, 2023

Well lets agree to disagree on that.

Mind you that having Sensorbox V3 taking over the modbus master role is a really bad idea, since the Sensorbox is optionally. There are a lot of alternatives out there that can get the Mains currents into the SmartEVSE.

@arpiecodes
Copy link
Contributor

Agreed with disagreeing. :-)

I was just referring to the Sensorbox as an example. I would also not mind it becoming a totally separate module.

In the near future not only your car will be talking over Homeplug GreenPHY; it will most probably become the basis for smart grid communication. So it can potentially also talk with (for example) solar inverters and other appliances like heatpumps, etc. Would be too bad if the module could not support such nice use cases. While I do agree that's out of scope (like you said with the alternatives that are there for main metering), why not consider it from the start? It would give so much more flexibility vs. making it a single-purpose solution.

I also don't see why having Sensorbox as the modbus master would be such a bad idea. It has been discussed here multiple times already. Nobody loses anything w/regards to functionality vs. current situation if you make it opt-in. If done in a correct way, would only mean the SmartEVSE can act as a Modbus slave which opens up a whole lot of extra possibilities in different set-ups as well. And would allow the SmartEVSE just to focus on that one thing it does best; be a charge controller without any added fuss.

Now, creating a whole different version of SmartEVSE as a whole sounds like complete overkill and would only make firmware management/updates more difficult, require everyone to replace their existing units, etc.

@dingo35
Copy link
Collaborator

dingo35 commented Mar 9, 2023

You will always need the possibility to have SmartEVSE working as modbus master, so having it also making it work as a slave increases complexity (both in code and in configuration).
Also it goes against the modbus architecture; all communication has to be initiated by the master by design. Almost all use cases are controllers (master) reading data from sensors (as slaves).

Id rather solve the structural problem of modbus only allowing one master by having the SmartEVSE functioning as a flexible configurable gateway from modbus to REST and/or MQTT, so it can interface to HomeAssistant or other more high-level domotica systems.

Just my 2 cents...

@arpiecodes
Copy link
Contributor

Id rather solve the structural problem of modbus only allowing one master by having the SmartEVSE functioning as a flexible configurable gateway from modbus to REST and/or MQTT, so it can interface to HomeAssistant or other more high-level domotica systems.

Which is in itself definitely not a bad idea/solution. I definitely support the motion to add more connectivity (e.g. REST API/MQTT, etc) to the SmartEVSE.

I just don't agree with the part where we'd add even more responsibilities/logic to the SmartEVSE's core code; including a whole new networking stack required to make GreenPHY work.

@arpiecodes
Copy link
Contributor

@arpiecodes I'm pretty interested in what CODICO has to say. Thanks for the link though, I hadn't spot the carrier boards before. I ordered one, will update you all. Like you said, pretty awesome to talk over IP with the car. I have also seen this one: https://www.codico.com/en/powerline-gp-evse-din-rail-modul-version-1-1 But holy smokes, that's not cheap for DIY.

My first plan is to setup a Raspberry PI with the board, and see if we can get some form of communication. Things I'm interested in are:

  • First of learning more about this topic, I'm a blank slate
  • Read car information, perhaps useful for authorization purposes
  • Read SoC and other information.

I also looked at the carrier board with a white beet instead, which has an ST32 microcontroller. However, if I understood correctly the sample code needs to be licensed, and I couldn't find sample code online. Otherwise, I'd like to have experimented with that instead.

Once this all works, we could make a PCB with small microcontroller and a RED beet that acts as a modbus slave for SmartEVSE to supply information about car SoC. (or SmartEVSE v4)

One thing I'm interested in to learn is how we deal with CP signal, as it is currently controlled by SmartEVSE, while pyPLC mentions that the PWM needs to be set to 5% duty cycle for a while to setup digital communication. Well, we'll see once the board arrives and things need to be wired. I usually learn these things from doing it wrong initially.

Hey @ArendJanKramer, were you able to try it out yet? I actually never heard back from CODICO and considering buying the carrier board anyways. Thought it'd be good to reach out to check how you are fairing with it first.

@ArendJanKramer
Copy link
Contributor

@arpiecodes I received the board. Wasn't exactly easy, they asked a lot of questions before they sent one over. Quality is really good, I'm impressed. Still working on getting a Raspberry PI, so I can actually start developing with it.

@fluppie
Copy link

fluppie commented May 7, 2023

@ArendJanKramer
Since I'm fan of having this functionality developed, could you work with a Raspberry Pi Zero 2W? Or do you need a 3B or 4?
I can sell you one ( for normal MSRP prices :) ) since I migrated most of my stuff to a LENOVO ThinkCentre M73 (see eBay, you can get them at 75-125 euros) with Proxmox VE on it. I can easily run 4-5 VM's with Debian etc on these machines with an i7 and 8GB of RAM.

@ArendJanKramer
Copy link
Contributor

@fluppie Thanks for the offer, I think I might be able to get one freed up in my setup. The Lenovo is actually a pretty good idea though lol.

Another question to the experts here is about zero-crossing and connecting the mains.
See picture of board without the lid:

IMG_3195
IMG_3194

You see "YT-35636 (292877)" modules used for [AC_L and AC_N] and [CP + PE].
The CP + PE pair makes sense for me, but I'm not so familiar for AC lines, is it needed for basic communication?
Because in fact, DC chargers are not using these pins am I right?

1 - https://www.codico.com/en/mpattachment/file/download/id/831/ section 5:
"Zero-cross detection has to be used in all applications with communication over AC mains or when module's
power supply is powers from AC mains. Two or more HomePlug AV/GreenPHY logical networks can only coexist
when zero-cross detection circuit is implemented.". In other words, not needed if only one car in the network right?
2 - The dev board has the proposed schematic in place though. Do I need it? Which phase do I connect here? Does it need to be the same phase as AC_L?
3 - According to components that I see, I can just connect SmartEVSE and this board to the same CP signal. I didn't do the math, but since only high frequent components would pass the capacitor on the dev board, the smartevse would still be able to see proper line voltages to negotiate charging with car. Likewise with duty cycle signal. Anyways, the worst that can happen is not a lot so I'll just give it a try I guess.

Again, I'm completely new to this ISO, but I'll learn as we go. "what can possibly go wrong"

@fluppie
Copy link

fluppie commented May 8, 2023

I would also think CP + PE is the way to go. Since the AC lines are disconnected by the contactor before charging.
Regarding connecting the CP in parallel, I think that's maybe a question for @mstegen ?
Maybe also check this document: https://github.com/uhi22/pyPLC/blob/master/doc/EvseMode.md

The CP of the vehicle is connected to the hot side of the homeplug modem and the hot side of the arduino-charging-logic. The PP of the car is connected to PE via 1k5 (inside the plug).

I also saw the earlier posted link to https://github.com/uhi22/pyPLC#example-flow which looks like interesting information

@ArendJanKramer
Copy link
Contributor

@fluppie Great resources, thanks for them. That seems hopeful.

I also read this thesis: https://ltu.diva-portal.org/smash/get/diva2:1546405/FULLTEXT01.pdf
Which is great for starters, but lacks some details, specifically on the AC side.

Regarding the 5% duty cycle to initiate communication, I see this in the code:
https://github.com/SmartEVSE/SmartEVSE-3/blob/main/SmartEVSE-3/src/evse.cpp#L557
When idle, there's no PWM signal. Perhaps by setting that to 5% duty cycle gets things running just as a test.

Maybe @mstegen can indeed confirm if it is safe to connect the dev board in parallel on the CP signal.

@mstegen
Copy link
Member

mstegen commented May 8, 2023

Great that you received your dev board.
I think you can connect the AC_L and AC_N to L and N of the SmartEVSE.
As the homeplug data is injected on the CP signal, you can connect the CP directly to the CP of the controller.
Ideally the EVSE should have a filter to suppress the homeplug HF signal.
(it's described in the ISO-15118_3 standard)

If you kill it somehow, let me know, and i'll replace it.

Ref the 5% PWM, this is required to start digital communication with the EV.
There is no harm in setting PWM to 5%, If the EV does not support it, it will reject it.
It has been part of the old J1772 standard, so even cars from 15+ years old should be able to handle it.

@ArendJanKramer
Copy link
Contributor

@mstegen Thank you for your suggestions and kind offer. Let's hope nothing breaks.

Good news so far, the PI and the Red Beet are talking:
afbeelding

I'll see if I can mount the components to some sort of board, so it's a bit less fragile.
IMG_3196

Next is modifying the firmware of SmartEVSE and then wiring. Fingers crossed

@MarkG-PE
Copy link

@uhi22 thank you for your early response.
Here i have attached the ethernet log from wireshark on the raspberry.
(i labelled it as .txt for support in Github file transfer. I could load it directly in wireshark, or it could be relabelled .pcapng as the original file type)

Thank you for any support.

ix3_run.txt

@uhi22
Copy link

uhi22 commented Aug 2, 2023

I stored the ix3_run.txt as pcap file, and used two methods to evaluate the content:

  1. use https://github.com/uhi22/pyPLC/blob/master/pcapConverter.py to extract the content of the EXI messages. Here we see, that the vehicle reports a full battery in the ChargeParameterDiscoveryReq: "DC_EVStatus.EVRESSSOC": "100". This could lead to the situation, that the car does not proceed in the charging process, because it sees no need to be charged.
  2. use wireshark to inspect the TCP traffic. Here we see, that at 18.273s the car sends a TCP frame which has the RESET flag set. This means, the car actively closes the connection. I guess this is because it is fully charged.

Summarized: This could be a "normal" behavior depending on the implementation on car side. Some cars do not even start a communication if the battery is full. Your seems to report the full battery and then close the connection.

It would be interesting whether the behavior changes if the SOC is lower.

@MarkG-PE
Copy link

MarkG-PE commented Aug 3, 2023

Prior to running the 100% SOC test, I ran a test with 71% and 45% SOC and I captured the python logs but unfortunately not the wireshark logs.
The result was exactly the same in the python output log and so i presume it will be the same in the wireshark log.
Here attached are the two python logs trials at 71% and 45% as noted above.

bmw ix3 log 71pc and 45pc.txt

In both cases the same outcome occurred as per the 100% SOC case.

If i am reading the Exi message correctly (based on Uhi22/pyPLC/results/2023-05-24_pyPlc_with_Ioniq93prcSoc.pcapng.decoded.txt lines 211 to 247), then the ESVE charge station is basically saying " i am a 200V to 450V charger with current output range 1A to 200A and i and ready to operate". But then the car sends Reset and closes the connection.

I am very new to this interpretation of Exi messages and Python, so i might be quite wrong.
I will drain the car SOC over the weekend and run the test with wireshark on lower SOC.

When i ran the test cases above, the car does the same thing each time as it resets. It sets the charge LED next to the plug to red (fault alarm) and reports on the drivers display, "Fault in the DC Charging Station" - maybe not exactly like that as its from memory, but that it the intent of the message.

@uhi22
Copy link

uhi22 commented Aug 4, 2023

Maybe the car does not like the ChargeParameterDiscoveryRes, because it does not contain valid units. Instead, the decoder sees "hours", e.g. here: EVSEMaximumPowerLimit.Unit": "h"
To resolve this, need to update the OpenV2Gx (https://github.com/uhi22/OpenV2Gx/blob/68850c94ecc95b0f67099463ade9176efcecf035/src/test/main_commandlineinterface.c#L1304C52-L1304C52) to write the Unit_isUsed=1 for all signals.

[Edit] Pushed on update: uhi22/OpenV2Gx@9ea2f72. Please pull the OpenV2Gx and recompile it, and try whether this helps.

@uhi22
Copy link

uhi22 commented Aug 4, 2023

An other potential root cause could be, that we report "DC_EVSEStatus.EVSEIsolationStatus": "1", which means "valid". On real charger, we see that they report 0, which means dinisolationLevelType_Invalid. Maybe the car expects the "Invalid" at this step.

[Edit] Pushed an update: uhi22/OpenV2Gx@d0e2281. Please pull and compile the OpenV2Gx.

@Electricalfan
Copy link

As a beginner, I want to ask basic question - do you read these values directly from CP pin via TCP? You capture them, scrape and project as information? The car sends information not as coded data, but for example "The SOC is xx %"?

@arpiecodes
Copy link
Contributor

arpiecodes commented Aug 17, 2023

As a beginner, I want to ask basic question - do you read these values directly from CP pin via TCP? You capture them, scrape and project as information? The car sends information not as coded data, but for example "The SOC is xx %"?

The car and the charging controller use PLC communication over the CP and PE pins. It's like having those AV HomePlugs that allow you to communicate over power lines; same basic concept.

The established PLC communication channel allows for your car and charge controller to talk to each other on IP level (so, indeed talk over TCP). The messages exchanged over TCP are standardised.

You can read more about it here; https://ltu.diva-portal.org/smash/get/diva2:1546405/FULLTEXT01.pdf and a full overview of the whole communication flow here; https://github.com/uhi22/pyPLC#example-flow.

@MarkG-PE
Copy link

@uhi22 wrote
“[Edit] Pushed an update: uhi22/OpenV2Gx@d0e2281. Please pull and compile the OpenV2G

I will test it in approx 2 weeks following vacation.
At same time I am testing switch iso15118 and I can compare differences in the car communications.

@MarkG-PE
Copy link

@Electricalfan you can download and read the communication from the text file i left above. You can see the detailed text read from Ethernet link to and from the car over a full slac session up to the point where it responds with the battery data and rated charge limitations. You open the file with wireshark.
Generally the car will send data followed by a power of 10 scaling factor. Then your program can read the data scale it and use it in a charging session.

@mhpetiwala
Copy link

mhpetiwala commented Sep 23, 2023

I tried to connect my setup to a Tesla model S 2018 (that has been converted to support NACS/CCS charging) but couldn't see any PLC comm on the wire from the EV after plugging in and setting the PWM to 5% duty cycle etc. Do I need to do anything different for Teslas v/s other CCSx vehicles? I am able to get it at least to a point of PLC comm with my setup but not for Teslas :-( any advice is appreciated.

I've tried this setup with Kia EV6 as well as Chevy Bolt and although I haven't been able to get it to close contactors and get to precharge state yet (still tweaking stuff based on pyPLC codebase and v2g) but with Tesla Model S and NACS/CCS1 charger I don't even see any PLC/GreenPHY comm even when the connector locks and I apply the correct voltage as well as 5% PWM duty cycle... anyone with Tesla experience and has got something working could comment and provide insights. Thx.

PS I was refered to this forum/messages by @uhi22 and thx to his repo I've been able to get so far yet...

@mstegen
Copy link
Member

mstegen commented Sep 25, 2023

I've got a Model S from 2018, and it's working for me. The car should start PLC comms, after you set 5% PWM.
I initially used the Redbeet-E dev board, with a Raspberry Pi, running pyPLC, and the serkri fork of the SmartEVSE software. But a ESP32 and Yellowbeet-E modem, together with https://github.com/SmartEVSE/ESP32-PLC should also work. You still need the SmartEVSE with Serkri software to set the PWM to 5% etc..
Please note that your modem needs to be set up to EVSE mode. See #25 (comment) for a RedBeet-E this is the standard setting.

@arpiecodes
Copy link
Contributor

arpiecodes commented Sep 25, 2023

I tried to connect my setup to a Tesla model S 2018 (that has been converted to support NACS/CCS charging) but couldn't see any PLC comm on the wire from the EV after plugging in and setting the PWM to 5% duty cycle etc. Do I need to do anything different for Teslas v/s other CCSx vehicles? I am able to get it at least to a point of PLC comm with my setup but not for Teslas :-( any advice is appreciated.

I've tried this setup with Kia EV6 as well as Chevy Bolt and although I haven't been able to get it to close contactors and get to precharge state yet (still tweaking stuff based on pyPLC codebase and v2g) but with Tesla Model S and NACS/CCS1 charger I don't even see any PLC/GreenPHY comm even when the connector locks and I apply the correct voltage as well as 5% PWM duty cycle... anyone with Tesla experience and has got something working could comment and provide insights. Thx.

PS I was refered to this forum/messages by @uhi22 and thx to his repo I've been able to get so far yet...

In order to understand what's going on with your Tesla, it'd be great to have some log output from pyPLC doing it's job and going through all the states. It may reveal where the communication gets stuck.

Also, @mstegen great work on ESP32-PLC. It seems to now contain everything we need for requesting the base SoC parameters? In that case I may be ordering an ESP32 with ModBus module soon and attempt to get my 'situation' in the electrical closet cleaned up a bit. :-) Direct connection between SmartEVSE and the PLC ESP32 would probably always be preferred with as less dependencies possible. Let's see if I can port it to ESPHome, would fit nicely next to the ESPHome-Sensorbox.

@mhpetiwala
Copy link

I tried to connect my setup to a Tesla model S 2018 (that has been converted to support NACS/CCS charging) but couldn't see any PLC comm on the wire from the EV after plugging in and setting the PWM to 5% duty cycle etc. Do I need to do anything different for Teslas v/s other CCSx vehicles? I am able to get it at least to a point of PLC comm with my setup but not for Teslas :-( any advice is appreciated.
I've tried this setup with Kia EV6 as well as Chevy Bolt and although I haven't been able to get it to close contactors and get to precharge state yet (still tweaking stuff based on pyPLC codebase and v2g) but with Tesla Model S and NACS/CCS1 charger I don't even see any PLC/GreenPHY comm even when the connector locks and I apply the correct voltage as well as 5% PWM duty cycle... anyone with Tesla experience and has got something working could comment and provide insights. Thx.
PS I was refered to this forum/messages by @uhi22 and thx to his repo I've been able to get so far yet...

In order to understand what's going on with your Tesla, it'd be great to have some log output from pyPLC doing it's job and going through all the states. It may reveal where the communication gets stuck.

Also, @mstegen great work on ESP32-PLC. It seems to now contain everything we need for requesting the base SoC parameters? In that case I may be ordering an ESP32 with ModBus module soon and attempt to get my 'situation' in the electrical closet cleaned up a bit. :-) Direct connection between SmartEVSE and the PLC ESP32 would probably always be preferred with as less dependencies possible. Let's see if I can port it to ESPHome, would fit nicely next to the ESPHome-Sensorbox.

pyPLC in EVSEmode is just waiting for the PEV - but even on wireshark I don't see any communication initiated at L2 /Homeplug GreenPHY side from the PEV. So logs on pyPLC won't help much as there is nothing inbound... a bit of a chicken and egg... I've this same setup working with CCS1 connector on Chevy Bolt as well as a Kia EV6 (but they are CCS1/CCS2 v/s Tesla is NACS - although they're actually using ISO15118 behind for the actual comm. Appreciate your help.

@mhpetiwala
Copy link

I've got a Model S from 2018, and it's working for me. The car should start PLC comms, after you set 5% PWM. I initially used the Redbeet-E dev board, with a Raspberry Pi, running pyPLC, and the serkri fork of the SmartEVSE software. But a ESP32 and Yellowbeet-E modem, together with https://github.com/SmartEVSE/ESP32-PLC should also work. You still need the SmartEVSE with Serkri software to set the PWM to 5% etc.. Please note that your modem needs to be set up to EVSE mode. See #25 (comment) for a RedBeet-E this is the standard setting.

Is it the EU/CCSx model or US/NACS? I have the NACS one - tried to find online help but no luck yet :-(

@mstegen
Copy link
Member

mstegen commented Sep 27, 2023

I've got a 2018 EU model S with CCS upgrade. If your model S has never had a hardware modification installed by Tesla, i don't think it's capable of CCS communication.
Tesla used one-wire CAN communication over CP line, for the Superchargers. But the newer stalls can both communicate over one-wire CAN or use a PLC modem.
If you connect a oscilloscope to the CP line, you should be able to see what signals the car supports.

@mhpetiwala
Copy link

I've got a 2018 EU model S with CCS upgrade. If your model S has never had a hardware modification installed by Tesla, i don't think it's capable of CCS communication. Tesla used one-wire CAN communication over CP line, for the Superchargers. But the newer stalls can both communicate over one-wire CAN or use a PLC modem. If you connect a oscilloscope to the CP line, you should be able to see what signals the car supports.


Yes. My car is updated with the CCS/NACS module and ECU. Got it done 2 months back. It was originally using the single wire CAN. I'll try to connect an oscilloscope and give it a shot.

@bssstudio
Copy link

Hello guys!

I have started investigating digital communications for EV charging equipment. Naturally, I discovered this thread/issue along with the relevant one on openinverter.org forum. I am interested in implementing the EVSE side - especially AC mode.

Hardware-wise, I am using TP-Link TL4010(p) and I managed to get my VW ID.4 to communicate firstly using @uhi22 pyPLC. I managed to get some data out of the car... However, I only have an AC (self-made DIY) EVSE, somewhat similar to SmartEVSE (I should have discovered this project sooner:)) so the DIN schema did not help me much in terms of getting the car to charge on AC.

I did however have success with the stack from SwitchEV: pyslac and iso15118. I had to modify the pyslac code to fake the SLAC attenuation values since TL4010 does not support this. Without this, the car would not connect. Then, with the iso15118 project, I managed to get an actual AC charging session going. I had to disable DIN schema to force it to talk using the ISO15118-2:2013.

Here is the log of the session from iso15118 secc side:

redis-1  | 1:C 27 Mar 2024 19:15:51.060 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-1  | 1:C 27 Mar 2024 19:15:51.060 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started
redis-1  | 1:C 27 Mar 2024 19:15:51.060 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis-1  | 1:M 27 Mar 2024 19:15:51.061 * monotonic clock: POSIX clock_gettime
redis-1  | 1:M 27 Mar 2024 19:15:51.061 * Running mode=standalone, port=6379.
redis-1  | 1:M 27 Mar 2024 19:15:51.061 # Server initialized
redis-1  | 1:M 27 Mar 2024 19:15:51.061 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis-1  | 1:M 27 Mar 2024 19:15:51.061 * Loading RDB produced by version 6.2.6
redis-1  | 1:M 27 Mar 2024 19:15:51.061 * RDB age 47 seconds
redis-1  | 1:M 27 Mar 2024 19:15:51.061 * RDB memory usage when created 0.77 Mb
redis-1  | 1:M 27 Mar 2024 19:15:51.061 # Done loading RDB, keys loaded: 0, keys expired: 0.
redis-1  | 1:M 27 Mar 2024 19:15:51.061 * DB loaded from disk: 0.000 seconds
redis-1  | 1:M 27 Mar 2024 19:15:51.061 * Ready to accept connections
secc-1   | DEBUG    2024-03-27 19:15:51,432 - asyncio (59): Using selector: EpollSelector
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (112): SECC settings:
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): NETWORK_INTERFACE             : enp0s13f0u2
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): LOG_LEVEL                     : DEBUG
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): SECC_ENFORCE_TLS              : False
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): FREE_CHARGING_SERVICE         : False
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): FREE_CERT_INSTALL_SERVICE     : True
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): USE_CPO_BACKEND               : False
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): ALLOW_CERT_INSTALL_SERVICE    : True
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): PROTOCOLS                     : ['ISO_15118_20_AC', 'ISO_15118_2']
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): AUTH_MODES                    : ['EIM', 'PNC']
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): STANDBY_ALLOWED               : True
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): PKI_PATH                      : /venv/lib/python3.10/site-packages/iso15118/shared/pki/
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): MESSAGE_LOG_JSON              : True
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): MESSAGE_LOG_EXI               : False
secc-1   | INFO    2024-03-27 19:15:51,433 - iso15118.secc.secc_settings (114): ENABLE_TLS_1_3                : False
secc-1   | DEBUG    2024-03-27 19:15:51,433 - iso15118.secc.controller.simulator (261): New Status: starting
secc-1   | INFO    2024-03-27 19:15:52,038 - iso15118.shared.exi_codec (177): EXI Codec version: 1.55
secc-1   | INFO    2024-03-27 19:15:52,038 - iso15118.secc (31): Starting 15118 version: 0.26.0
secc-1   | INFO    2024-03-27 19:15:52,038 - iso15118.secc.comm_session_handler (235): Communication session handler started
secc-1   | INFO    2024-03-27 19:15:52,039 - iso15118.secc.transport.udp_server (137): UDP server socket ready
secc-1   | INFO    2024-03-27 19:15:52,039 - iso15118.secc.transport.udp_server (123): UDP server started at address FF02::1%enp0s13f0u2 and port 15118
secc-1   | DEBUG    2024-03-27 19:15:52,049 - iso15118.secc.controller.simulator (261): New Status: ready


secc-1   | DEBUG    2024-03-27 19:20:38,597 - iso15118.secc.transport.udp_server (158): Message received from ('fe80::27d:faff:fe06:c772', 49152, 0, 266): 01fe9000000000020000
secc-1   | INFO    2024-03-27 19:20:38,598 - iso15118.secc.comm_session_handler (437): SDPRequest received: [Security: TLS, Protocol: TCP]
secc-1   | INFO    2024-03-27 19:20:38,606 - iso15118.secc.transport.tcp_server (134): TLS server started at address fe80::9143:9541:b1b2:d654%enp0s13f0u2 and port 56242
secc-1   | INFO    2024-03-27 19:20:38,617 - iso15118.secc.comm_session_handler (464): Sending SDPResponse: [ IP address: fe80::9143:9541:b1b2:d654, Port: 56242 , Security: TLS , Transport: TCP ]
secc-1   | DEBUG    2024-03-27 19:20:39,737 - iso15118.secc.transport.udp_server (158): Message received from ('fe80::27d:faff:fe06:c772', 49153, 0, 266): 01fe9000000000021000
secc-1   | INFO    2024-03-27 19:20:39,737 - iso15118.secc.comm_session_handler (437): SDPRequest received: [Security: NO_TLS, Protocol: TCP]
secc-1   | INFO    2024-03-27 19:20:39,737 - iso15118.secc.comm_session_handler (379): Reset current tcp handler.
secc-1   | WARNING    2024-03-27 19:20:39,737 - iso15118.secc.transport.tcp_server (149): Closing TCP server
secc-1   | INFO    2024-03-27 19:20:39,740 - iso15118.secc.transport.tcp_server (134): TCP server started at address fe80::9143:9541:b1b2:d654%enp0s13f0u2 and port 56242
secc-1   | INFO    2024-03-27 19:20:39,750 - iso15118.secc.comm_session_handler (464): Sending SDPResponse: [ IP address: fe80::9143:9541:b1b2:d654, Port: 56242 , Security: NO_TLS , Transport: TCP ]
secc-1   | INFO    2024-03-27 19:20:39,788 - iso15118.secc.transport.udp_server (201): UDP server has been paused.
secc-1   | INFO    2024-03-27 19:20:39,788 - iso15118.secc.comm_session_handler (284): TCP client connected, client address is ('fe80::27d:faff:fe06:c772', 49153, 0, 266).
secc-1   | INFO    2024-03-27 19:20:39,794 - iso15118.shared.comm_session (347): Starting a new communication session
secc-1   | INFO    2024-03-27 19:20:39,794 - iso15118.shared.states (139): Entered state SupportedAppProtocol
secc-1   | DEBUG    2024-03-27 19:20:39,794 - iso15118.shared.states (143): Waiting for up to 20.0 s
secc-1   | INFO    2024-03-27 19:20:39,891 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2010:AppProtocol): {"supportedAppProtocolReq":{"AppProtocol":[{"ProtocolNamespace":"urn:din:70121:2012:MsgDef","VersionNumberMajor":2,"VersionNumberMinor":0,"SchemaID":1,"Priority":1},{"ProtocolNamespace":"urn:iso:15118:2:2013:MsgDef","VersionNumberMajor":2,"VersionNumberMinor":0,"SchemaID":0,"Priority":2}]}}
secc-1   | INFO    2024-03-27 19:20:39,892 - iso15118.shared.comm_session (236): supportedAppProtocolReq received
secc-1   | INFO    2024-03-27 19:20:39,892 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2010:AppProtocol): {"supportedAppProtocolRes": {"ResponseCode": "OK_SuccessfulNegotiation", "SchemaID": 0}}
secc-1   | INFO    2024-03-27 19:20:39,909 - iso15118.secc.states.sap_states (147): Chosen protocol: ISO_15118_2
secc-1   | INFO    2024-03-27 19:20:39,909 - iso15118.shared.comm_session (432): Sent supportedAppProtocolRes
secc-1   | INFO    2024-03-27 19:20:39,909 - iso15118.secc.controller.simulator (764): iso15118 state: SupportedAppProtocol
secc-1   | INFO    2024-03-27 19:20:39,909 - iso15118.shared.states (139): Entered state SessionSetup
secc-1   | DEBUG    2024-03-27 19:20:39,909 - iso15118.shared.states (143): Waiting for up to 20.0 s
secc-1   | INFO    2024-03-27 19:20:40,037 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"00"},"Body":{"SessionSetupReq":{"EVCCID":"007DFA06C772"}}}}
secc-1   | INFO    2024-03-27 19:20:40,037 - iso15118.shared.comm_session (236): SessionSetupReq received
secc-1   | INFO    2024-03-27 19:20:40,038 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"SessionSetupRes": {"ResponseCode": "OK_NewSessionEstablished", "EVSEID": "UK123E1234", "EVSETimeStamp": 1711567240}}}}
secc-1   | INFO    2024-03-27 19:20:40,076 - iso15118.shared.comm_session (432): Sent SessionSetupRes
secc-1   | INFO    2024-03-27 19:20:40,076 - iso15118.secc.controller.simulator (764): iso15118 state: SessionSetup
secc-1   | INFO    2024-03-27 19:20:40,076 - iso15118.shared.states (139): Entered state ServiceDiscovery
secc-1   | DEBUG    2024-03-27 19:20:40,076 - iso15118.shared.states (143): Waiting for up to 60.0 s
secc-1   | INFO    2024-03-27 19:20:40,196 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ServiceDiscoveryReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:40,196 - iso15118.shared.comm_session (236): ServiceDiscoveryReq received
secc-1   | INFO    2024-03-27 19:20:40,197 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ServiceDiscoveryRes": {"ResponseCode": "OK", "PaymentOptionList": {"PaymentOption": ["ExternalPayment"]}, "ChargeService": {"ServiceID": 1, "ServiceName": "AC_DC_Charging", "ServiceCategory": "EVCharging", "FreeService": false, "SupportedEnergyTransferMode": {"EnergyTransferMode": ["AC_three_phase_core"]}}}}}}
secc-1   | INFO    2024-03-27 19:20:40,231 - iso15118.shared.comm_session (432): Sent ServiceDiscoveryRes
secc-1   | INFO    2024-03-27 19:20:40,231 - iso15118.secc.controller.simulator (764): iso15118 state: ServiceDiscovery
secc-1   | INFO    2024-03-27 19:20:40,345 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"PaymentServiceSelectionReq":{"SelectedPaymentOption":"ExternalPayment","SelectedServiceList":{"SelectedService":[{"ServiceID":1}]}}}}}
secc-1   | INFO    2024-03-27 19:20:40,345 - iso15118.shared.comm_session (236): PaymentServiceSelectionReq received
secc-1   | INFO    2024-03-27 19:20:40,345 - iso15118.shared.states (139): Entered state PaymentServiceSelection
secc-1   | DEBUG    2024-03-27 19:20:40,345 - iso15118.shared.states (143): Waiting for up to 60.0 s
secc-1   | DEBUG    2024-03-27 19:20:40,345 - iso15118.secc.states.iso15118_2_states (624): EVCC chose authorization option ExternalPayment
secc-1   | INFO    2024-03-27 19:20:40,346 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"PaymentServiceSelectionRes": {"ResponseCode": "OK"}}}}
secc-1   | INFO    2024-03-27 19:20:40,374 - iso15118.shared.comm_session (432): Sent PaymentServiceSelectionRes
secc-1   | INFO    2024-03-27 19:20:40,374 - iso15118.secc.controller.simulator (764): iso15118 state: PaymentServiceSelection
secc-1   | INFO    2024-03-27 19:20:40,465 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"AuthorizationReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:40,465 - iso15118.shared.comm_session (236): AuthorizationReq received
secc-1   | INFO    2024-03-27 19:20:40,465 - iso15118.shared.states (139): Entered state Authorization
secc-1   | DEBUG    2024-03-27 19:20:40,466 - iso15118.shared.states (143): Waiting for up to 60.0 s
secc-1   | INFO    2024-03-27 19:20:40,466 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"AuthorizationRes": {"ResponseCode": "OK", "EVSEProcessing": "Finished"}}}}
secc-1   | INFO    2024-03-27 19:20:40,495 - iso15118.shared.comm_session (432): Sent AuthorizationRes
secc-1   | INFO    2024-03-27 19:20:40,495 - iso15118.secc.controller.simulator (764): iso15118 state: Authorization
secc-1   | INFO    2024-03-27 19:20:40,495 - iso15118.shared.states (139): Entered state ChargeParameterDiscovery
secc-1   | DEBUG    2024-03-27 19:20:40,495 - iso15118.shared.states (143): Waiting for up to 60.0 s
secc-1   | INFO    2024-03-27 19:20:40,645 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargeParameterDiscoveryReq":{"MaxEntriesSAScheduleTuple":192,"RequestedEnergyTransferMode":"AC_three_phase_core","AC_EVChargeParameter":{"EAmount":{"Multiplier":0,"Unit":"Wh","Value":5300},"EVMaxVoltage":{"Multiplier":0,"Unit":"V","Value":272},"EVMaxCurrent":{"Multiplier":-1,"Unit":"A","Value":624},"EVMinCurrent":{"Multiplier":-1,"Unit":"A","Value":15}}}}}}
secc-1   | INFO    2024-03-27 19:20:40,645 - iso15118.shared.comm_session (236): ChargeParameterDiscoveryReq received
secc-1   | INFO    2024-03-27 19:20:40,646 - iso15118.shared.exi_codec (248): 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}}]}}
secc-1   | INFO    2024-03-27 19:20:40,670 - iso15118.shared.exi_codec (248): 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"}]}}
secc-1   | INFO    2024-03-27 19:20:40,692 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613", "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": "Dw4H+7ZR974vqKSONmn1WxpPNVQ9WbsYusl22+ShuHPMr+n+QtQQEwxStYEW2TP47Lfu/rzb6agZG21JjW7YhA=="}}}, "Body": {"ChargeParameterDiscoveryRes": {"ResponseCode": "OK", "EVSEProcessing": "Finished", "SAScheduleList": {"SAScheduleTuple": [{"SAScheduleTupleID": 1, "PMaxSchedule": {"PMaxScheduleEntry": [{"PMax": {"Value": 4500, "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": 8, "Multiplier": 0, "Unit": "A"}}}}}}
secc-1   | INFO    2024-03-27 19:20:40,721 - iso15118.shared.comm_session (432): Sent ChargeParameterDiscoveryRes
secc-1   | INFO    2024-03-27 19:20:40,721 - iso15118.secc.controller.simulator (764): iso15118 state: ChargeParameterDiscovery
secc-1   | INFO    2024-03-27 19:20:40,721 - iso15118.shared.states (139): Entered state PowerDelivery
secc-1   | DEBUG    2024-03-27 19:20:40,721 - iso15118.shared.states (143): Waiting for up to 60.0 s
secc-1   | INFO    2024-03-27 19:20:40,797 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"PowerDeliveryReq":{"ChargeProgress":"Start","SAScheduleTupleID":1,"ChargingProfile":{"ProfileEntry":[{"ChargingProfileEntryStart":0,"ChargingProfileEntryMaxPower":{"Multiplier":2,"Unit":"W","Value":45}}]}}}}}
secc-1   | INFO    2024-03-27 19:20:40,797 - iso15118.shared.comm_session (236): PowerDeliveryReq received
secc-1   | DEBUG    2024-03-27 19:20:40,798 - iso15118.secc.states.iso15118_2_states (1884): EV last Profile start 0s is within time range [0; 86400[ and power range: EV Max 4500 W <= EVSE Max 4500 W 
secc-1   | 
secc-1   | DEBUG    2024-03-27 19:20:40,798 - iso15118.secc.states.iso15118_2_states (1670): ChargeProgress set to Start
secc-1   | DEBUG    2024-03-27 19:20:40,798 - iso15118.secc.states.iso15118_2_states (1787): State is C2
secc-1   | INFO    2024-03-27 19:20:40,798 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"PowerDeliveryRes": {"ResponseCode": "OK", "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:40,827 - iso15118.shared.comm_session (432): Sent PowerDeliveryRes
secc-1   | INFO    2024-03-27 19:20:40,827 - iso15118.secc.controller.simulator (764): iso15118 state: PowerDelivery
secc-1   | INFO    2024-03-27 19:20:40,827 - iso15118.shared.states (139): Entered state ChargingStatus
secc-1   | DEBUG    2024-03-27 19:20:40,827 - iso15118.shared.states (143): Waiting for up to 60.0 s
secc-1   | INFO    2024-03-27 19:20:42,168 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:42,169 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:42,169 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:42,191 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:42,191 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:42,259 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:42,259 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:42,260 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:42,294 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:42,294 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:42,431 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:42,431 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:42,432 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:42,447 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:42,447 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:42,582 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:42,583 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:42,583 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:42,600 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:42,600 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:42,731 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:42,731 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:42,732 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:42,745 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:42,745 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:42,883 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:42,883 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:42,883 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:42,897 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:42,897 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:43,034 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:43,034 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:43,034 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:43,049 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:43,049 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:43,197 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:43,197 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:43,198 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:43,221 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:43,221 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:43,353 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:43,353 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:43,353 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:43,366 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:43,366 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:20:43,504 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:20:43,504 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:20:43,505 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:20:43,517 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:20:43,517 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus

=====
...omitted...
=====

secc-1   | INFO    2024-03-27 19:28:00,914 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:28:00,914 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:28:00,914 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:28:00,925 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:28:00,925 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:28:01,053 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:28:01,053 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:28:01,054 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:28:01,063 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:28:01,063 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:28:01,196 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"ChargingStatusReq":{}}}}
secc-1   | INFO    2024-03-27 19:28:01,196 - iso15118.shared.comm_session (236): ChargingStatusReq received
secc-1   | INFO    2024-03-27 19:28:01,196 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"ChargingStatusRes": {"ResponseCode": "OK", "EVSEID": "UK123E1234", "SAScheduleTupleID": 1, "EVSEMaxCurrent": {"Value": 7, "Multiplier": 0, "Unit": "A"}, "ReceiptRequired": false, "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:28:01,207 - iso15118.shared.comm_session (432): Sent ChargingStatusRes
secc-1   | INFO    2024-03-27 19:28:01,207 - iso15118.secc.controller.simulator (764): iso15118 state: ChargingStatus
secc-1   | INFO    2024-03-27 19:28:01,315 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"PowerDeliveryReq":{"ChargeProgress":"Stop","SAScheduleTupleID":1,"ChargingProfile":{"ProfileEntry":[{"ChargingProfileEntryStart":0,"ChargingProfileEntryMaxPower":{"Multiplier":2,"Unit":"W","Value":45}}]}}}}}
secc-1   | INFO    2024-03-27 19:28:01,315 - iso15118.shared.comm_session (236): PowerDeliveryReq received
secc-1   | INFO    2024-03-27 19:28:01,315 - iso15118.shared.states (139): Entered state PowerDelivery
secc-1   | DEBUG    2024-03-27 19:28:01,315 - iso15118.shared.states (143): Waiting for up to 60.0 s
secc-1   | DEBUG    2024-03-27 19:28:01,315 - iso15118.secc.states.iso15118_2_states (1884): EV last Profile start 0s is within time range [0; 86400[ and power range: EV Max 4500 W <= EVSE Max 4500 W 
secc-1   | 
secc-1   | DEBUG    2024-03-27 19:28:01,315 - iso15118.secc.states.iso15118_2_states (1670): ChargeProgress set to Stop
secc-1   | INFO    2024-03-27 19:28:01,315 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"PowerDeliveryRes": {"ResponseCode": "OK", "AC_EVSEStatus": {"NotificationMaxDelay": 0, "EVSENotification": "None", "RCD": false}}}}}
secc-1   | INFO    2024-03-27 19:28:01,326 - iso15118.shared.comm_session (432): Sent PowerDeliveryRes
secc-1   | INFO    2024-03-27 19:28:01,326 - iso15118.secc.controller.simulator (764): iso15118 state: PowerDelivery
secc-1   | INFO    2024-03-27 19:28:01,326 - iso15118.shared.states (139): Entered state SessionStop
secc-1   | DEBUG    2024-03-27 19:28:01,326 - iso15118.shared.states (143): Waiting for up to 60.0 s
secc-1   | INFO    2024-03-27 19:28:02,406 - iso15118.shared.exi_codec (304): Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"63293AA43DA79613"},"Body":{"SessionStopReq":{"ChargingSession":"Terminate"}}}}
secc-1   | INFO    2024-03-27 19:28:02,406 - iso15118.shared.comm_session (236): SessionStopReq received
secc-1   | INFO    2024-03-27 19:28:02,407 - iso15118.shared.exi_codec (248): Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "63293AA43DA79613"}, "Body": {"SessionStopRes": {"ResponseCode": "OK"}}}}
secc-1   | INFO    2024-03-27 19:28:02,416 - iso15118.shared.comm_session (432): Sent SessionStopRes
secc-1   | INFO    2024-03-27 19:28:02,416 - iso15118.secc.controller.simulator (764): iso15118 state: SessionStop
secc-1   | INFO    2024-03-27 19:28:02,416 - iso15118.shared.comm_session (398): The data link will terminate in 2 seconds and the TCP connection will close in 5 seconds. 
secc-1   | INFO    2024-03-27 19:28:02,416 - iso15118.shared.comm_session (402): Reason: EV requested to terminate the communication session
secc-1   | INFO    2024-03-27 19:28:04,418 - iso15118.secc.controller.simulator (1097): Session ended in SessionStop (EV requested to terminate the communication session).
secc-1   | INFO    2024-03-27 19:28:04,418 - iso15118.shared.comm_session (411): terminated the data link
secc-1   | INFO    2024-03-27 19:28:07,422 - iso15118.shared.comm_session (417): [Errno 104] Connection reset by peer
secc-1   | INFO    2024-03-27 19:28:07,422 - iso15118.shared.comm_session (418): TCP connection closed to peer with address ('fe80::27d:faff:fe06:c772', 49153, 0, 266)
secc-1   | WARNING    2024-03-27 19:28:07,422 - iso15118.secc.transport.tcp_server (149): Closing TCP server
secc-1   | INFO    2024-03-27 19:28:07,422 - iso15118.secc.transport.udp_server (209): UDP server has been resumed.

The car responded to AC current limitation (EVSEMaxCurrent) in ChargingStatusRes messages from EVSE to PEV.
One thing bothered me though, the car never reported SoC inside the ISO15118-2 AC session. It did, when I tried to simulate DC charging, but not with AC. I am unable to get any information since the ISO standard is behind a paywall.

@uhi22, do you have any idea, how to convince the car to report SoC during AC session?

Please let me know if you need any pointers on how to set-up the pyslac/iso15118 or if you would like me to test something with my EV with iso15118.

@uhi22
Copy link

uhi22 commented Mar 28, 2024

These are very interesting news, thanks for this.
Regarding SOC during AC charging: I have no idea. The question would be, does the car really not send it, or does the SwitchEV not decode it correctly. If you have a wireshark running including the iso15118 decoder, this should tell you the truth. If the car really is just sending nothing (what means nothing, always 0? Or is this an optional field?), I guess we need to complain at VW ;-)

Nevertheless I have two questions:

  1. Did you manage to find out, what is the blocking point to use DIN for AC charging? My first impression, based on the OpenV2G exi decoder was, that basically also DIN could support AC. Maybe it isn't, but would be interesting at which point there is the blocker.
  2. It would be really great to write down your way how you made the SwitchEV running. This would help a lot of people to use this. At the moment my impression is, the entry barriere is quite high. I have no idea where would be a good place to write such a summary, so that everybody finds it. Maybe even in the openinverter wiki or forum, something like "how to setup SwitchEV".

[Edit] The message set for AC seems to be quite limited. The ISO from 2016 defines an empty request, this means the vehicle does not transfer any data to the charger while charging. This would explain, that the charger cannot know the SOC. What bullshit, they specified a large number of crazy things and forgot about the simplest. I had a look to the OpenV2X exi decoder, also there, in the DIN and in the ISO1 schema, the dinChargingStatusReqType has no content.
However, in the ISO2, we find that the iso2ChargingStatusReqType contains some elements, and in DisplayParameters we find CurrentSOC and CurrentSOC_isUsed. This means: Using the right version of the ISO could reveal the SOC, but still it is an optional field for which VW needed to decide whether they want to send it or not.

@mhpetiwala
Copy link

These are very interesting news, thanks for this. Regarding SOC during AC charging: I have no idea. The question would be, does the car really not send it, or does the SwitchEV not decode it correctly. If you have a wireshark running including the iso15118 decoder, this should tell you the truth. If the car really is just sending nothing (what means nothing, always 0? Or is this an optional field?), I guess we need to complain at VW ;-)

Nevertheless I have two questions:

  1. Did you manage to find out, what is the blocking point to use DIN for AC charging? My first impression, based on the OpenV2G exi decoder was, that basically also DIN could support AC. Maybe it isn't, but would be interesting at which point there is the blocker.
  2. It would be really great to write down your way how you made the SwitchEV running. This would help a lot of people to use this. At the moment my impression is, the entry barriere is quite high. I have no idea where would be a good place to write such a summary, so that everybody finds it. Maybe even in the openinverter wiki or forum, something like "how to setup SwitchEV".

[Edit] The message set for AC seems to be quite limited. The ISO from 2016 defines an empty request, this means the vehicle does not transfer any data to the charger while charging. This would explain, that the charger cannot know the SOC. What bullshit, they specified a large number of crazy things and forgot about the simplest. I had a look to the OpenV2X exi decoder, also there, in the DIN and in the ISO1 schema, the dinChargingStatusReqType has no content. However, in the ISO2, we find that the iso2ChargingStatusReqType contains some elements, and in DisplayParameters we find CurrentSOC and CurrentSOC_isUsed. This means: Using the right version of the ISO could reveal the SOC, but still it is an optional field for which VW needed to decide whether they want to send it or not.

I agree, I've been looking at the switchEV stack but barrier to get it setup is much higher than @uhi22 pyplc component. If I remember the Everest project I'd also moving to a newer stack away from JOSEV, correct? Hence would be great if @bssstudio can provide some steps on how you got it running.

Decode the messages using the charge point v2g dissector it would help understand what messages it payload values are being sent/recv.

@bssstudio
Copy link

Yes, it was quite finicky with lots of trial and error to get it running. Pyslac did not want to run in docker, so I managed to get it running locally on linux, but iso15118 did not want to run locally, but I got it running in docker with host mode. I will find the time to retrace my steps and try to get something useful to enable others to test it - will try to focus on getting everything running in docker so that it is more repeatable and not related to my environment.

I will try to do another session today and capture the pcap on the eth interface that is connected to the modem and also try to get the iso15118 to output the raw undecoded messages.

@uhi22 Is iso1 = iso15118-2 and iso2 = iso15118-20? I tried a session with only ISO15118-20_AC protocol allowed, but the EV and software failed to negotiate a protocol and the session was terminated by the software stack. I am trying to figure out if VW ID.4 actually supports iso15118-20. Maybe there is more data transmitted with the iso15118-20?

I will be back soon with the traces.

@bssstudio
Copy link

I have completed traces and logs for a few different scenarios:

  • ISO15118-2, AC 3ph, 2.75A of current limit (2024-03-28_iso15118-2_ac3ph_4_2.75amp) - CHARGING
  • DIN, AC 3ph, 2.7A of current limit (2024-03-28_din_ac3ph_6_2.7amp) - FAILED - wrong energy transfer mode
  • ISO15118-20, AC 3ph, TLS1.3 (2024-03-28_iso15118-20_ac3ph_6_tls1.3) - FAILED - TLS error - unknown CA
  • ISO15118-20, AC 3ph, TLS (2024-03-28_iso15118-20_ac3ph_7_tls) - FAILED - TLS error - unknown CA

I suspected since I remember reading somewhere that TLS is mandatory for ISO15118-20 (please correct me if I am wrong - I can not get a definitive answer since I don't have the ISO standard documents), that my EV is not even adding the ISO15118-20 as a possible schema because of unsecured connection (no TLS). Plug and charge definitely requires TLS - this was my reasoning that maybe ISO15118-20 also needs TLS for the car to even request it. My EV did try to establish a TLS session even when it was not specifically configured in SECC, but failed with an "unknown CA" error. That would be correct behavior since my certificates are self-signed and thus should not be trusted by definition. Does anyone know where I could get a CPO (SECC) certificate that is signed by V2G root CA or any tier1 or tier2 downstream certificates? Who even is the V2G CA for Europe? I have seen hubject has some PKI certificates for V2G. I need to investigate further. Any info much appreciated.

I have also tried simulating both SECC(EVSE) and EVCC(PEV) from the iso15118 project with ISO15118-20 AC and there wasn't any mention of SoC anywhere in the communication - maybe this is just because it is a simulation and optional parts are omitted. I need to study the code to see what is going on.

The DIN spec did not want to work with AC 3ph mode although it is mentioned in the XML schema (who knows?). The SECC(EVSE) sent the energy transfer mode as AC 3phase and the car happily confirmed it but later requested DC charging, ignoring what was negotiated earlier.

There is however good news in all this, why it still might be worth pursuing iso15118-2 AC mode: digitally set current limit. Analog PWM mode has a bizarre 6A minimum current limit in the standard that is limiting when charging from PV systems to self-consume as much energy as possible. My EV (ID.4) communicated a minimum current limit of 1.5A. It however did not work correctly when set to 2A (it drew 2A from one phase and 0.45A from the other two). The minimum current I got to work reliably was 2.7A from all 3 phases resulting in a combined 1800W of power draw in a 3-phase system (only 400W more than 6A single phase on 230V systems). This alone is worth pursuing as it might be possible to get 1.8kW - 11/22kw range of power control from the EVSE.

I might also have a theory/idea on how to get the SoC data from the EV. There might be a possibility of renegotiating energy transfer modes, essentially to trick the EV into thinking it will establish DC charging session (to tell us the SoC) but before there is any cable checks/power transfer try to renegotiate to AC 3-phase energy transfer mode and do a normal charging session. Then periodically try to renegotiate to DC to get the SoC and back to AC to charge. I am still struggling with how to make multiple charging sessions without disconnecting the cable - sometimes after a successful charging session (when EVSE sets PWM to 12V steady) the car will start another session when set to 5% PWM. Sometimes it will not and I have to disconnect and reconnect the cable. It is quite OK with the "analog mode" to restart charging when PWM reappears. I have to try terminating the session "digitally" with EVSENotification and see if this helps or setting the current to 0A to see if the car will wait in this state. This is necessary for PV self-consumption and home power management/load balancing.

I have attached traces and screenshots.

Screenshot from 2024-03-28 20-53-16

2024-03-28_din_ac3ph_6_2.7amp.txt
2024-03-28_iso15118-2_ac3ph_4_2.75amp.txt
2024-03-28_iso15118-20_ac3ph_6_tls1.3.txt
2024-03-28_iso15118-20_ac3ph_7_tls.txt
pcap_traces.zip

@arpiecodes
Copy link
Contributor

arpiecodes commented Mar 30, 2024

@bssstudio those are very good and valid questions! I don't think any of us really got this far yet.

I would also really really like a signed cert to build out such a more 'total' integrated charging solution. But it seems to be largely 'managed' away from the public, behind closed doors etc (just like the standard itself). However, maybe there's mention of the third parties managing the top-level CA's in the standard docs. Maybe @mstegen could take a look there? In any case, I estimate the chance you'll get a signed cert for yourself without any commercial intent/resources to be quite small. But we can dream. :-)

I might also have a theory/idea on how to get the SoC data from the EV. There might be a possibility of renegotiating energy transfer modes, essentially to trick the EV into thinking it will establish DC charging session (to tell us the SoC) but before there is any cable checks/power transfer try to renegotiate to AC 3-phase energy transfer mode and do a normal charging session. Then periodically try to renegotiate to DC to get the SoC and back to AC to charge. I am still struggling with how to make multiple charging sessions without disconnecting the cable - sometimes after a successful charging session (when EVSE sets PWM to 12V steady) the car will start another session when set to 5% PWM.

This is actually what we do in the serkri fork of SmartEVSE-3 now. We first negotiate a session with the car/initiate modem communication. Get e.g. the EVCCID, SoC, max charge values from car, max battery capacity etc. After all the info has been gathered, we reset the charging session and skip the 5% PWM cycle (so no digital communication). The car will then proceed to just charge the 'normal' non-digital (analog) way, but we do have all the important information we need to make our own 'educated guesses'. These data can then all be combined to give 1) the current SoC at start session, 2) the estimated current charged SoC at any time by looking at the energy already charged with a KwH meter vs what the requested KwH amount was, 3) make a rough estimation of when it's done charging based on the current charge speeds, etc. No need to switch back to digital mode for the remainder of the session.

serkri#205
serkri#160

The above should already give you the basics for the 'smart charging' decisions, but you still can't dip below 6A I'm afraid. :-(

Screenshot 2023-10-30 at 17 31 39

Currently the solution is kind of a 'poor man's plug 'n charge'. I'd really like to explore whether there's more reliable ways to e.g. identify the car. Maybe by initiating a SSL cert exchange and taking note of the CN, if the car sends theirs first. That would be perfect and much more reliable vs. using the EVCCID, which could in theory be spoofed.

But hey.... I don't think people around my charge point at home actually have hacker-level knowledge on EV charge sessions, so the chance that ever being exploited are probably not abysmal. In the meantime, I really like the fact I can just plug in the car and it will start charging. No need to switch access on/off anymore or swipe RFID's, as it knows my car by it's ID. :)

The one thing I'd like to improve in my set-up is get rid of the Raspberry Pi Zero I need now to handle the modem communication. It feels too messy to send such data over API calls. I'd rather replace it with a ESP32 that communicates with the SmartEVSE through Modbus (like the Sensorbox), or UART. Obviously it would be awesome if SmartEVSE 4 already has a modem built in, but it would also increase it's pricepoint. Having a way to include it in a modular way to existing installations would also be nice. Which is why I'm hoping to some day land on a solution that's a hybrid between Sensorbox and the Pi I currently use. It seems @mstegen has done a lot of the hard (leg) work already to get the basics ported over to run on the ESP32. Just need to put it all together now.

@MarkG-PE
Copy link

MarkG-PE commented Apr 2, 2024

I resolved all my issues with closed connection on the bmwix3 as described here
uhi22/pyPLC#14 (comment)
Thank you @uhi22

@devdems
Copy link
Contributor

devdems commented Apr 22, 2024

Can someone who has this implemented make a summary of what is needed to make this work? I can't see in any documentation that this would be covered even if it is experimental.

I see on @dingo35 and serkri repo's that you have #define "MODEM 0 //0 = no modem 1 = modem" so I guess the SW part should be covered with this from the SmartEVSE side.

What else is needed from the HW and how the connection works?

@poohnet
Copy link

poohnet commented May 18, 2024

@bssstudio:
I had to modify the pyslac code to fake the SLAC attenuation values since TL4010 does not support this.

Could you please explain what kind of modification to the pyslac code has to be done?

Thanks :-)

@bssstudio
Copy link

@bssstudio: I had to modify the pyslac code to fake the SLAC attenuation values since TL4010 does not support this.

Could you please explain what kind of modification to the pyslac code has to be done?

Thanks :-)

Sorry for the long delay to reply.

Here is the commit that enabled me to use tplink 4010: commit

@poohnet
Copy link

poohnet commented Jun 30, 2024

Here is the commit that enabled me to use tplink 4010: commit

Thank you very much for providing your fix :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests