I (almost) completely reverse engineered the API today: it’s not really secure, but that’s “good” for us.
I have gone through the whole process several times with fresh Android setups. Several tokens/keys remained the same, which is why I don’t blur them.
In the first step, we authenticate against the Google 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:
600
{
"kind": "identitytoolkit#VerifyPasswordResponse",
"localId": "<importantLocalId>",
"email": "<yourEmail>",
"displayName": "<yourUsername>",
"idToken": "<tokenYouCanGetGoogleAccountInformation>",
"registered": true,
"refreshToken": "<someNotUsesToken>",
"expiresIn": "3600"
}
In next steps we need only the “localId” for API requests. Now, we need our session ID for get information about our lawn mower:
POST https://api-de.devicewise.com/api HTTP/2.0
accept: application/json
content-type: application/json
content-length: 161
accept-encoding: gzip
user-agent: okhttp/4.9.0
{"auth":{"command":"api.authenticate","params":{"appToken":"DJMYYngGNEit40vA","appId":"<importantLocalId>","thingKey":"<importantLocalId>"}}}
The domain of the API endpoint was always the same regardless of my language setting. The correspondence with the Google API, not further mentioned here, did not return a country code.
The request brings us a SessionID. Unfortunately, we do not know when it expires:
{"auth":{"success":true,"params":{"orgKey":"ZUCCHETTICENTROSISTEMI","sessionId":"<importantSessionId>"}}}
In the next requests we need to include the SessionID as HTTP header.
Now a little Bluetooth magic happens. The IMEI of your lawn mower is determined.
POST https://api-de.devicewise.com/api HTTP/2.0
accept: application/json
sessionid: <importantSessionId>
content-type: application/json
accept-encoding: gzip
user-agent: okhttp/4.9.0
{"thing_find":{"command":"thing.list","params":{"show":["id","key","name","connected","lastSeen","lastCommunication","loc","properties","alarms","attrs","createdOn","storage","varBillingPlanCode"],"keys":["<imeiOfYourMover>"],"hideFields":true}}}
You will get back all requested parameters.
Next, I will try to determine the control commands.