Phil242 / reverse-besen-API

GNU Affero General Public License v3.0
16 stars 2 forks source link

Decompiled protocol #5

Open bakkerrs opened 1 year ago

bakkerrs commented 1 year ago

Hi! Thanks for your work so far on this.

I decompiled the EVSE Master app itself in an attempt to understand the protocol better. The app has a list of commands embedded in it. It doesn't actually utilize all commands available, so I don't have an understanding of all commands. I've written some notes which you can find here.

What's the status on your investigation? Let me know if there's anything I can do to help further.

ceesgeert commented 1 year ago

Decompiling is great work and a lot of command detail. Thank you. Is there a certain command sequence to authenticate required? Before getting the login response? Login CMD=0x01 originated "d" in the table is that correct? and what is the data structure for a login command

bakkerrs commented 4 months ago

Hi @ceesgeert So the following seems to happen:

None of the commands sent by the app have any data attached (other than a single empty byte (0x00)) up until login is confirmed.

From that point the wallbox seems to accept other commands and regularly spits out information. After about half a minute the wallbox stops accepting new commands and starts sending login packets again at which point you need to re-authenticate.

johnwoo-nl commented 3 months ago

Hi all,

I recently got a Telestar EC311S wallbox which also uses the EVSEMaster app, and the protocol discussed here. I'm building a webapp for managing the wallbox to get around the LAN-only functionality of the app (aside from its apparent phoning home and insisting on reconnecting via BT, even though the wallbox stays active on LAN). I'm only just starting, your findings so far have proven very helpful, but I've come with one deviation from your findings, one addition, and one question.

  1. I noticed that my wallbox sometimes puts 2 message datagrams in a single UDP packet. There is no separator or anything; the second datagram's 0x0601 header will immediately follow the first datagram's 0x0f02 tail. Suggest to update the docs to take this into account. The solution I took was to process the first datagram from offset 0, and while there are bytes left in the UDP packet after processing the datagram, repeat the process using the earlier datagram(s) length(s) as offset. I did not see it place 3 datagrams in a packet yet but this way the code would handle that.

  2. The Login (0x0001) datagrams that the wallbox broadcasts have the same payload as the LoginResponse (0x0002) datagram as described in @bakkerrs document.

  3. ~I'm seeing all the repeating Login datagrams, however I don't seem to get any LoginResponse after sending a RequestLogin datagram to the wallbox (either with valid or invalid password). I'm not sure why exactly; I've tried sending the datagram to the originating port of the Login broadcast packets I received earlier, and (just to check) also to the app port 28376. I've also tried both 0x00 and 0x01 as the single-byte payload. Any ideas? Which port are you sending the commands to?~ Never mind, I packed one of the 16-bit words little-endian accidentally ;)

I'll investigate more and post back any further findings.

b2un0 commented 3 months ago

@johnwoo-nl can you share your code? I would like to adopt this as nodejs mqtt app

johnwoo-nl commented 3 months ago

@johnwoo-nl can you share your code? I would like to adopt this as nodejs mqtt app

[offtopic] Sorry, nothing to share yet. I'm only at the login flow. However I am splitting this into two parts from the start; a library for EVSE communication (protocol abstraction using nodejs dgram), and a separate Nuxt webapp on top of that. The library could be reused by other projects, like smarthome integrations. I'll create projects for each when they're at least usable.

johnwoo-nl commented 3 months ago

Hi @ceesgeert So the following seems to happen:

  • The Wallbox spits out Login (0x0001) packets on a regular basis.

  • The app responds with a RequestLogin (0x8002) packet which includes the password of the wallbox (default '123456')

  • The Wallbox responds with a LoginResponse (0x0002) packet which contains some additional information about the wallbox

  • The app then confirms the login with a LoginConfirm (0x8001) packet.

None of the commands sent by the app have any data attached (other than a single empty byte (0x00)) up until login is confirmed.

From that point the wallbox seems to accept other commands and regularly spits out information. After about half a minute the wallbox stops accepting new commands and starts sending login packets again at which point you need to re-authenticate.

Some more findings on the discovery, login and session management:

  1. The wallbox broadcasts Login (0x0001) packets about once every 5 seconds only if it isn't actively communicating with a logged-in client. Once someone is "logged in" it stops doing that (at least I didn't see a Login anymore while I was keeping my session alive - see next points).
  2. If another client wishes to login, that client can still initiate a login by directly sending a RequestLogin (0x8002) to the last-known IP of the wallbox. The wallbox will respond with a LoginResponse (0x0002) just the same. The payloads of the Login broadcast and the targeted LoginResponse are the same.
  3. Such a second client would need to know the IP of the wallbox. Discovery via the Login broadcasts won't work while another client is communicating. I tried broadcasting the RequestLogin with all-null password and serial, but that results in a PasswordErrorResponse (0x0155) from any wallboxes on that port. That at least will allow discovery of new wallbox IPs. Unfortunately, no wallbox information is returned until a LoginResponse is received after you send out a LoginRequest containing the correct password (or the Login discovery broadcasts resume when the active client is done). So for this type of discovery, the user would have to enter a password before any info like serial number, brand or model can be determined...
  4. The LoginConfirm (0x8001) sent by the client marks the actual moment of login: the wallbox will accept commands and will also start sending Heading (0x0003) datagrams to the client every 10 seconds (the first one immediately in response to the LoginConfirm).
  5. The client should respond to these Heading messages with a HeadingResponse (0x8003) datagram. This keeps the session alive. If the client does not respond with a HeadingResponse, then at the 3rd missed round (so about 30 seconds) the wallbox won't take commands anymore - the client is "logged out" and would need to RequestLogin again. At this point the wallbox will also resume sending Login broadcasts.
  6. There does not seem to be a way to log out explicitly - just stop responding to the Heading datagrams and you'll be "logged out" after ~30 seconds. Or perhaps sending a datagram with an invalid password will invalidate the session; when sending a datagram with an invalid password, the wallbox replies with a PasswordErrorResponse (0x0155) but I didn't verify yet if it actually stops taking commands or if client could continue with valid password datagrams.
johnwoo-nl commented 2 months ago

Okay, here's another finding, unfortunately not a nice one...

The protocol defines a command setAndGetOutputElectricity (0x8107) and its response, setAndGetOutputElectricityResponse (0x0107), used for setting the charging amperage (between 6 and the maximum value supported by the charger as returned in the outputElectricity field of the Login broadcast and LoginResponse -- 16A for most 3-phase EVSEs). I was very much hoping this would allow me to vary the charging speed of a session on the fly (ultimately I wanted to control it based on PV solar output). And I honestly expected it to work, because the chargeStart (0x8007) command for starting a session has a field to specify the initial amperage, so why else have a separate command for changing the amps?

If I send this command during a session, I see the EVSEMaster app does indicate the new value I set next to the "Max current" label in the "Current charging setting" section. However, the charging session unfortunately keeps going at the same speed set when it was started (as reported by the charger via the singleACStatus (0x0004) datagrams, and also in the car app I see the initial amps value still being shown). This goes for higher but also lower values; neither is applied. So this value is apparently not communicated with the car via the CP pin during a session, but only used when starting one.

This is a major bummer, since it severely limits the options for varying the charging speed. It is of course possible to stop a session and start a new one with a different amps setting, but you don't want to do this often; stopping and restarting a session dis- and re-engages the high-voltage contactors in the car's onboard charger, wearing them out eventually (also, it takes some time to do as the new session is negotiated between EVSE and car). I'm afraid for this (varying charging speed based on PV output) to work properly, we'd need a different firmware in the EVSE that can actually communicate a new setting with the car during a session. Or perhaps some brands can do this (that would explain the separate command plus the initial amps setting in chargeStart) and it's just my cheap Telestar that is not feature complete...

b2un0 commented 1 week ago

any new state on this? for the beginning i like to have a simple read only docker container running a nodejs mqtt client to publish only sensor values.

johnwoo-nl commented 6 days ago

any new state on this? for the beginning i like to have a simple read only docker container running a nodejs mqtt client to publish only sensor values.

Actually I was recently working on the library part and while by far not done, it is perhaps functional enough to publish for testing. Here is a repo: https://github.com/johnwoo-nl/emproto

It is a library meant to be used by other projects (I'm working on a Nuxt app for accessing my wallbox and ditching the OEM app), but there is also a small CLI utility for some simple testing.

I tested with my own Telestar EC311S and the features that it currently has all work on my wallbox:

(Sorry for the plug, it's not actually about protocol research, but probably interesting enough for anyone working on the EvseMaster protocol...)

b2un0 commented 6 days ago

many thanks @johnwoo-nl

Thank you very much! The house we bought already had an EVSE wallbox from the previous owner. I will use your library to display the current status of the wallbox with mqtt.