sHedC / homeassistant-ambrogio

Home Assistant Integration for the Ambrogio Robot Mowers
MIT License
2 stars 2 forks source link

Allow Setup using Firebase API as per Mobile App #28

Closed sHedC closed 1 year ago

sHedC commented 1 year ago
          I have checked the complete flow of the mobile app again. We can find the model via the Firebase API. However, from my point of view, the path is not worth it, since two other APIs have to be connected.

In the first step, we authenticate against the Google API service with email address and password:

POST https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=AIzaSyCUGSbVrwZ3X7BHU6oiUSmdzQwx-QXypUI HTTP/1.1
Content-Type: application/json
X-Android-Package: it.centrosistemi.ambrogioremote
X-Android-Cert: 4753441615021C6147D5F0946A0DA83877EF3D41
Accept-Language: en-US
X-Client-Version: Android/Fallback/X21000008/FirebaseCore-Android
X-Firebase-GMPID: 1:373506005239:android:07fcd128132313f3
X-Firebase-Client: H4sIAAAAAAAAAKtWykhNLCpJSk0sKVayio7VUSpLLSrOzM9TslIyUqoFAFyivEQfAAAA
Content-Length: 84
User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86_64 Build/PSR1.180720.122)
Host: www.googleapis.com
Connection: Keep-Alive
Accept-Encoding: gzip

{"email":"<yourEmail>","password":"<yourPassword>","returnSecureToken":true}

We get an JSON formatted response with important tokens:

{
  "kind": "identitytoolkit#VerifyPasswordResponse",
  "localId": "<importantLocalId>",
  "email": "<yourEmail>",
  "displayName": "<yourUsername>",
  "idToken": "<importantAccessToken>",
  "registered": true,
  "refreshToken": "<someNotUsesToken>",
  "expiresIn": "3600"
}

Next step, we create a websocket connection to Firebase API

GET wss://centrosistemi-ambrogioremote.firebaseio.com/.ws?ns=centrosistemi-ambrogioremote&v=5 HTTP/1.1
Host: centrosistemi-ambrogioremote.firebaseio.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: nQybC2IH64qOZ05V1ffn9g==
X-Firebase-AppCheck: null
User-Agent: Firebase/5/20.0.6/28/Android
X-Firebase-GMPID: 1:373506005239:android:07fcd128132313f3
content-length: 0

Authentication and get with this account connected lawn mowers:

▼ {"t":"c","d":{"t":"h","d":{"ts":1681166772961,"v":"5","h":"s-usc1a-nss-2058.firebaseio.com","s":"<someUnusedKey>"}}}
▲ {"t":"d","d":{"a":"s","r":0,"b":{"c":{"sdk.android.20-0-6":1,"persistence.android.enabled":1}}}}
▼ {"t":"d","d":{"r":0,"b":{"s":"ok","d":""}}}
▲ {"t":"d","d":{"a":"auth","r":1,"b":{"cred":"<importantAccessToken>"}}}
▼ {"t":"d","d":{"r":1,"b":{"s":"ok","d":{"auth":{"name":"<yourAccountName>","email_verified":false,"provider":"password","email":"<yourEmailAddress>","user_id":"<importantLocalId>","token":{"name":"<yourAccountName>","email_verified":false,"email":"<yourEmailAddress>","exp":1681169388,"user_id":"<importantLocalId>","iat":1681165788,"sub":"<importantLocalId>","aud":"centrosistemi-ambrogioremote","auth_time":1681165788,"iss":"https://securetoken.google.com/centrosistemi-ambrogioremote","firebase":{"identities":{"email":["<yourEmailAddress>"]},"sign_in_provider":"password"}},"uid":"<importantLocalId>"},"expires":1681169388}}}}
▲ {"t":"d","d":{"a":"q","r":2,"b":{"p":"robots\\/ambrogio\\/<importantLocalId>","h":""}}}
▼ {"t":"d","d":{"b":{"p":"robots/ambrogio/<importantLocalId>","d":{"00:00:00:00:00:00":{"boardserial":"AM03500000000000","btAddress":"00:00:00:00:00:00","imei":"350000000000000","modelType":"","name":"L35 Deluxe","password":"0","programId":75,"remoteDisplayAvailable":true,"revision":61532,"timestamp":1682949301697}}},"a":"d"}}

Through this way we could do in config flow the authentication by email and password and get the IMEI of the robots this way. We would then also have the model. However, the path is also more fragile against changes to any of the API.

I believe that we can also determine the model from the serial number that we get via the Devicewise API. In the example above, you can see that I have an L35 Deluxe and my serial number starts with AM035. However, I have too few robots (only one) to verify this. ;-) If we knew more, we could create a mapping.

The mobile app only gets the battery level via bluetooth. We would have to sniff the bluetooth traffic for this. I have not opened this Pandora's box yet.

Originally posted by @ufozone in https://github.com/sHedC/homeassistant-ambrogio/issues/22#issuecomment-1532979020

sHedC commented 1 year ago

@ufozone - I was thinking of bluetooth in the future if I ever get to understand it. I did sniff the Bluetooth but don't much understand it.

I have a bluetooth proxy for HASS, low power has bluetooth and wifi was thinking of either installing by the base station or inside the robot. It's a future project :)

sHedC commented 1 year ago

You can find my Options and Config Flow here: https://github.com/ufozone/ha-zcs-mower/blob/main/custom_components/zcsmower/config_flow.py

I think the following breaking changes will be necessary:

sHedC commented 1 year ago

@ufozone - I see your zcs mower is much more complete is it worth me doing an Ambrogio integration or contribute to your ZCS one? I see your ZCS seems to be for Ambrogio but you mention other robots?

I have updated the configure to pick up the settings from the firebase API but not yet done anything on the ID as not had a lot of time.

ufozone commented 1 year ago

@sHedC - Both integrations are slightly different in base. At a certain stage of development, I could no longer maintain both integrations in parallel. Authentication in my ZCS integration is still via the client key. The Firebase Auth would be much more comfortable - but I don't have time for the implementation.

ZCS Zucchetti has several brands under which it sells lawn mowers - Ambrogio, Techline, Wiper, ... Different name, same hardware, same functions, same Connect module, same API, same commands....

Ambrogio-only integration is not worth it from my point of view - only for discoverability for end users. Your repository has already spread in some forums and is more findable on Google than mine.

sHedC commented 1 year ago

@ufozone - Ok makes sense I will continue.

I will look to separating out the API logic to its own module maybe that will make some sense if it becomes useful, like I did with the MasterthermConnect module.

Didn't know my integration was a topic of conversation :)