Code Monkey home page Code Monkey logo

Comments (25)

ahochsteger avatar ahochsteger commented on August 21, 2024 3

I'd like to share my findings about how the Solar.Wattpilot App communicates with Fronius Wattpilot.

It provides a websocket connection at port 80 on the IP address that is connected to the WIFI.
Using this websocket debug tool and the URL ws://<local_ip>/ws I was able to successfully connect and receive these JSON messages - a hello message and an authorization required message.

Here is the log output:

$ _INFO_:Connect success, url = ws://<local_ip>/ws
$ _INFO_:Received message: {"type":"hello","serial":"<serialnr>","friendly_name":"Wattpilot_<serialnr>","manufacturer":"fronius","devicetype":"wattpilot","version":"34.5","protocol":2,"secured":true}
$ _INFO_:Received message: {"type":"authRequired","token1":"siHWIFSGNfQQuqHXR9J3nrJOdbaHAZui","token2":"1dsfbEciJtkyCPCd01rbAC8RuKel7b3n"}

<serialnr> is a 8-digit number.
token1 and token2 are changed on every connection

The next step would be to find out how to do the authentication but that seems to be a bit more challenging ;-).
In the Android App the authentication is done using the serial number and a password.
Using trial and error the authentication message seems to have this format:

$ _INFO_:send message, content = {"type":"auth","serial":"<serialnr>","token3":"asdf","hash":"asdf"}
$ _INFO_:Received message: {"type":"authError","message":"Wrong password"}

Unfortunately I have no idea how to calculate token3 and hash, but maybe someone else finds a way to successfully authenticate ...

from sensor.fronius.

joscha82 avatar joscha82 commented on August 21, 2024 2

another update: With @ebiiii hint i was able to send updates to the Wallbox and set property "cae" to True. (Enable Cloud API) "cak" property contains a api-key afterwards which is usable as descripted in official documentation: https://github.com/goecharger/go-eCharger-API-v2/blob/main/cloudapi-de.md

-> Wattpilot already contains a working e-go CloudAPI but the command to enable it is disabled in the App as of now.

Updates send to the wattpilot are secured with hmac-sha256

message:

{
"type":"setValue",
"requestId":"1",
"key":"cae",
"value":True
}

securedMsg:

{
"type":"securedMsg",
"requestId": "1sm" -> RequestID of contained message + "sm" (e.g. "1sm")
"data": -> message,
"hmac": ->HMAC-SHA256 with key=password and data=message with original encoding
}

from sensor.fronius.

sirathan avatar sirathan commented on August 21, 2024 1

The normal Symo works. I have a Wattpilot installed working with a Symo 10

from sensor.fronius.

ebiiii avatar ebiiii commented on August 21, 2024 1

From the disassembled code (and a lot of guessing), I figured out that the hash is computed as follow (where the + is a string concatenation):
hash = CryptoJS.SHA256(token3 + token2 + CryptoJS.SHA256(token1 + password))
and was able to confirm it with the values from an actual authentication exchange.
Regarding the token3, I would assume it's just some random value to add some salt in the hashing.

from sensor.fronius.

colwilliamsnz avatar colwilliamsnz commented on August 21, 2024

There doesn't appear to be an open API for the Wallbox. Given it talks directly to the inverter maybe its possible to get sensor values from the Solar API but I can't find anything documented. If you find something I suggest you update this request so it can be looked into further.

from sensor.fronius.

tim-ad08 avatar tim-ad08 commented on August 21, 2024

from sensor.fronius.

nilrog avatar nilrog commented on August 21, 2024

From what I have managed to find so far there is no API for the Wattpilot. It talks directly to the inverter via WiFi to obtain information from the smartmeter/inverter. So I would not be surprised if the only way to control and read info from the Wattpilot is by using their App for the Wattpilot.

In one Fronius document they also write that it requires a Symo Hybrid or Gen24 inverter, not a regular Symo, to be able to regulate based on surplus PV power. I do hope that is not true because I am really interested in this charger and I have a Symo.

This is from the Prerequsites in the "Data communication with the inverter" section from their manual:
https://manuals.fronius.com/html/4204260400/en.html#0_m_0000024045

The inverter is supported (Fronius GEN24, Fronius Symo Hybrid, Fronius SnapINverter, except Light versions).

from sensor.fronius.

hudeldudel avatar hudeldudel commented on August 21, 2024

@ahochsteger

The auth request for connected devices looks like this:

{
  "type": "auth",
  "token3": "ac7d78c4852b1c...",
  "hash": "a18652ee70ddf.."
}

Currently, I also have no idea how to compute the token. I assume it needs to be created with some key that got exchanged during the setup process and the tokens provided from the previous response. Currently, I also have no idea how to compile the message hash.

The auth response looks like:

{
  "type": "authSuccess",
  "token3": "ac7d78c4852b1c...",
  "hash": "a18652ee70ddf..."
}

The device then sends a message of type fullStatus.

{
  "type": "fullStatus",
  "partial": true,
  "status": {
    "mod": 1,
    "rfb": 1663,
    "stao": null,
    "alw": false,
    "acu": null,
    "acui": null,
    "adi": true,
    "dwo": null,
    "tpa": 0,
    "sse": "32453543",
    "eto": 39809,
    "etop": 39809,
    "wifis": [
       ...
    ],
    ... some other fields
    }
}

The device then sends messages with type deltaStatus

{
  "type": "deltaStatus",
  "status": {
    "rfb": 1663,
    "ehs": 280924,
    "efh": 146636,
    "efh32": 146636,
    "efh8": 107956,
    "utc": "2021-12-22T22:39:01.118",
    "loc": "2021-12-22T23:39:01.118 +01:00",
    "rbt": 33320614,
    "tma": [
      8.75,
      14
    ],
    "fhz": 49.988,
    "tpcm": [
      5,
      0,
      3,
      1,
      1,
      0,
      1,
      1,
      34,
      2,
      2,
      1,
      0,
      41,
      0,
      1,
      0,
      0,
      1,
      0,
      0
    ]
  }
}

If you change e. g. amps by sending

{
  "type": "securedMsg",
  "data": "{\"type\":\"setValue\",\"requestId\":\"1\",\"key\":\"amp\",\"value\":14}",
  "requestId": "1sm",
  "hmac": "07cb34eb9c49fa9c2f64a1b2cfd..."
}

It will respond like this

{"type":"response","requestId":"1","success":true,"status":{"amp":14}}

Exploring the API is quite easy if you can tcpdump the local traffic e. g. of the app from your access point.
But without understanding how the token for the auth request is compiled, it makes no sense to dig deeper into the other messages. Decompiling e. g. the Android app APK could provide additional insights. But that's not my area of expertise.

from sensor.fronius.

joscha82 avatar joscha82 commented on August 21, 2024

I think you have an error in the auth request:

Hallo (Wallbox->Client):

{
"type":"hello",
"message":"Hello app",
"serial":"12345678",
"devicetype":"wattpilot",
"manufacturer":"fronius",
"protocol":2
}

Auth Request (Wallbox->Client):

{
"type":"authRequired",
"token1":"1234567890ABCDEFGHIJKabcdefghijk",
"token2":"abcdefghijk1234567890ABCDEFGHIJK"
}

Authentification (Client->Wallbox):

{
"type":"auth",
"token3":"4f...",
"hash":"2b..."
}

Auth Success (Wallbox->Client):

{
"type":"authSuccess",
"message":"Successfully authenticated"
}

token1, token2, token3 are 32character Strings consisting of [a-Z0-9]. Hash is 64 characters [a-Z0-9].

sqlite database of Android App contains the following data:

[{
"type":2,
"serial":"12345678",
"password":"5H...",
"name":"Wattpilot_12345678"
}]

Password again is 32 char [a-Z0-9].

I also could not reconstruct how token3 is generated.

Endpoint is either <IP_of_Wattpilot>/ws or https://app.wattpilot.io/app/<serialnumber_of_wattpilot>?version=x.y.z. Updates send to local IP (unencrypted http) contain a hmac to secure the message itself. Updates send over https via cloud are not secured:

Update send to cloud:

{
"type":"setValue",
"requestId":"15",
"key":"bac",
"value":false
}

Update send to local IP:

{
"type":"securedMsg",
"data": {\"type\":\"setValue\",\"requestId\":\"1\",\"key\":\"trx\",\"value\":0}",
"requestId":"1sm",
"hmac":"a5..."   (64 characters [a-Z0-9])
}

I have no clue how token3 or hmac is calculated tho....

from sensor.fronius.

hudeldudel avatar hudeldudel commented on August 21, 2024

I took a look at the Android APK to find out how the token3 and the hmac hash are generated. As far as I understand it, only the appearance is defined in the Java code. The app itself is a react native app bundled to assets/index.android.bundle.

I embedded the code in an html file and then threw it into the Chrome debugger.

  1. The code is probably obfuscated.
  2. The JavaScript code cannot be executed in Chrome on Mac: Uncaught SyntaxError: Invalid or unexpected token

Can it be better analyzed if the app is run in the Android emulator?

Update:
The app runs Hermes JavaScript engine. The code in the bundle is Hermes bytecode. It is possible to disassemble with hbctool but that's still not easy to debug.

from sensor.fronius.

nilrog avatar nilrog commented on August 21, 2024

@hudeldudel I admire you attempt to reverse engineer this...and I hope that you succeed :)

It's sad that Fronius has opted to make the Wattpilot a separate entity with no official API. They took a good product (go-echarger) and turned it into an inferior product...apart from the smartmeter integration.
I did ask Fronius about their weird statement regarding inverter support in the documentation and just like @sirathan mentioned above, the regular SYMO works.

Personally I have ditched the Wattpilot, that I almost bought, and I will go for the go-echarger instead. The only thing I will not get out-of-the-box compared to the Wattpilot is the smartmeter integration to aid in maximizing charging without blowing fuses. But since it has an API and I am already running HA fixing that is a no brainer.

from sensor.fronius.

hudeldudel avatar hudeldudel commented on August 21, 2024

@nilrog I have stopped trying to reverse engineer. It's gotten to a point where I don't think it's worth it anymore for me.

My two main use cases are not working unless there is some usable API:

  1. Since the Fronius Smart Meter for my GEN 24 is currently not available, I wanted to control the charging power based on my existing SML measurements.
  2. I also wanted to stop charging at a SOC of 80%. The SOC is obtained via the vehicle's API.

Case 1. should work for people that already own the required smart meter. There will probably be one available for me soon.
Alternatively, I could now rather fake the API of the inverter including mDNS discovery etc. in order to trick and control the wallbox. Or I could fake the missing smart meter by translating my SML measurements to Modbus RTC Sunspec and pass it to the GEN24. But I don't like the last solution because I don't know what can happen with it.

Case 2. may be achieved by setting appropriate values with the workarounds for case 1.

I can't motivate myself to do this at the moment because I'm dissatisfied for now. Not offering an API is just so weak for such kind of product.

Knowing what I know now, I wouldn't have bought the Fronius Wattpilot either.

But Fronius might surprise us and deliver some API with a firmware update. Fingers crossed...

from sensor.fronius.

joscha82 avatar joscha82 commented on August 21, 2024

@ebiiii Thank you very much. I can also confirm this as correct, just confirmed this with some older dump of the auth exchange and also connected fine with random- 32Byte Hex Value for token3.

Password is not the Device-Password but the value stored in the App-sqlite DB. Not sure yet how this is obtained.

from sensor.fronius.

mze9412 avatar mze9412 commented on August 21, 2024

Edit becasue somehow I wrote in German ...

I have activated the cloud api with this method but it seems Wattpilot is not connecting to it. I get the API key from the fullStatus dump.
I see on my internal DNS server that wattpilot only ever contacts iot.wattpilot.io and the go-e API returns statuscode 403 (either wrong token or charger is not connected to API).

The serial I have has 8 digits, the go-e API docu talks about 6 digit serials. Is that maybe an issue?

At least I have my own nodejs based code now to read and write values. Thanks for all the reverse engineering!

from sensor.fronius.

mze9412 avatar mze9412 commented on August 21, 2024

Because I did not see it mentioned: The hashed password is just a 'simple' sha512 password derivative. It uses the password as password and the serial number of the wattpilot as salt. The result is shorted to the first 32 characters. I create it like this:
pbkdf2Sync(this._password, msg.serial, 100000, 256, 'sha512').toString('base64').substring(0, 32);

EDIT
Ah, also found your github repo, which does the same in python :D

from sensor.fronius.

joscha82 avatar joscha82 commented on August 21, 2024

Because I did not see it mentioned: The hashed password is just a 'simple' sha512 password derivative. It uses the password as password and the serial number of the wattpilot as salt. The result is shorted to the first 32 characters. I create it like this: pbkdf2Sync(this._password, msg.serial, 100000, 256, 'sha512').toString('base64').substring(0, 32);

EDIT Ah, also found your github repo, which does the same in python :D

My repo? I have added some code here which peforms the auth (also in the way you mentioned (100.000 rounds of sha512 hmac).

https://github.com/joscha82/wattpilot

I enabled and tested the eGo API a while ago and found it working, i cannot remember which URL i used, i believe i used the ego URL just with the longer serial.
However, i am not a friend of utilizing the eGo Cloud API as this may be unlicensed (and consumes ressources from eGo) as long as the service is not officially enabled by fronius.
My example code however should be able to perform all actions: Read all Properties and set all properties and should work local and over the internet (by utilizing the wattpilot websocket endpoint in the cloud insteat of the Local Websocket). Cloud Websocket behaviours almost identical to the local websocket endpoint, only change is that the hallo message contains other properties and that send messages are not required to be signed (as the connection itself is ssl encrypted).

from sensor.fronius.

mze9412 avatar mze9412 commented on August 21, 2024

Yeah, that is the repo I meant :)

My nodejs solution (not yet pushed it anywhere) basically does something very similar to your solution. I only need something to toggle the loading mode (eco, next trip, charge) and I need to change which car is connected anyway :)

from sensor.fronius.

joscha82 avatar joscha82 commented on August 21, 2024

My nodejs solution (not yet pushed it anywhere) basically does something very similar to your solution. I only need something to toggle the loading mode (eco, next trip, charge) and I need to change which car is connected anyway :)

Yes same intention here: active eco mode when SoC > 40%, enable Trip Mode when < 40%, disable both modes when Soc < 20%.

Disable Charging if distance car <> home > 200m and enable otherwise

from sensor.fronius.

ahochsteger avatar ahochsteger commented on August 21, 2024

@joscha82 here's a PR to your great work to extend it with an interactive shell that allows inspecting of all available Wattpilot properties and changing them as well:
joscha82/wattpilot#1

from sensor.fronius.

okoohler avatar okoohler commented on August 21, 2024

@joscha82 Great effort in making this! I'm trying to enable cae on my Wallbox but only get an error:
Skärmavbild 2022-03-23 kl  12 37 36
It's probably user error on my part, but do you know what might be wrong?

from sensor.fronius.

ahochsteger avatar ahochsteger commented on August 21, 2024

@okoohler, have you tried using set cae true (lower-case) instead?
There's a difference between Python and JSON (True vs. true) that may not be so obvious.

from sensor.fronius.

okoohler avatar okoohler commented on August 21, 2024

@ahochsteger thanks for your reply. Yes, I've tried lower case and even 1 (as in 0 or 1 for false/true).

from sensor.fronius.

ahochsteger avatar ahochsteger commented on August 21, 2024

@okoohler thanks for reporting it was indeed a bug in setting boolean values.
It's already fixed here:
joscha82/wattpilot#5

from sensor.fronius.

okoohler avatar okoohler commented on August 21, 2024

from sensor.fronius.

ahochsteger avatar ahochsteger commented on August 21, 2024

@joscha82, @okoohler and this PR adds simple MQTT support - so initial integration with Home Assistant using it's MQTT support might already be possible with a bit of tweaking:
joscha82/wattpilot#6

Still the best would be to add it to the fronius integration ...
Any chance for it, @safepay?

from sensor.fronius.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.