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 1 month 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 1 month 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 1 month ago

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

johnwoo-nl commented 1 month 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 weeks 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.