Please add support for maytronics dolphin pool cleaner

I also bought a 40i, let me know if I can help. I can program a little but don’t know phyton, think I may help in realize how to access with differenze serial.

I generated python code from postman, and it gives me the expected response.

import requests

url = "https://mbapp18.maytronics.com/api/users/Login/"

payload='Email=xxxx&Password=yyyy'

headers = {

  'appkey': 'zzzzz',

  'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'

}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

however – i think i forgot an important piece of the puzzle. You need to send an appkey header. Its a GUID thats generated by the client app.

i obtained mine by sniffing app traffic using mitmproxy. Im not sure if theres another way to get it.

1 Like

That was definitely it! I setup mitmproxy and nabbed my appkey. I tell you what though, I’m not sure how we’re going to figure out how to obtain this appkey … I wonder if the appkey is generated and not actually account specific and if that’s the case, we gotta figure out the mechanism for creating it.

For giggles I took my appkey and changed 1 character and immediately I was met with unauthorized =\

I was able to also mitmproxy using google as a login method and that may actually be pretty easy too using the google python library. But whatever that’s for another day.

Any idea on the appkey part? If we can figure that out then we’re in business.

If we sniffed the traffic when you first sign in to the app on a new device, that might show how its created.

Unfortunately im an android user so i have to borrow my wifes phone every time i want to try and sniff traffic.

@lordlala have you made any further progress ?
I havent had a chance to look at this in the last little while.

Doesnt help that my robot is offline and wont reconnect either!

I had serious problems too, so I flushed all data from the Android app, reconnected it to the robot, and it solved it.

Hey guys-
I’m no good with code, but I’m happy to test! I have the T45 and would love to do my part to get this integration working. Let me know if anything I can do.

My Dolphin is alive! Kind of!

Thanks to a post on the Pool Math website, I discovered Dolphin pool robots have an Automation Mode, meaning you can power the control box on/off with a WiFi outlet or switch, and the robot will start cleaning upon the box receiving power.

The post:

Update…It most certainly is available! I had to work hard with Maytronics customer service, but they got an Engineer on the horn, and Here’s how you set the Dolphin E20 up to work via a smart plug…

  1. Make sure the unit is powered OFF
  2. Press and hold the weekly schedule button for 10-15 sec, until the scheduling lights FLASH.
  3. Immediately press the Power Button to ON. (The E20 should operate in the pool).
  4. Now unplug the AC Power, attach your respective WiFi/Zigbee/ZWave…smart plug and plug the E20 unit into the Smart Plug
  5. When power comes on…the E20 should now start working.

Now when you turn on the smart outlet, your robot should automatically start cleaning within a few seconds. Simply power off your outlet to stop the robot.

Thanks to this, I no longer need the Dolphin app as I now use my smart plug with scheduled on/off automations, and buttons to suspend the schedule or quick clean the pool integrated into my dashboard. Works flawlessly.

Now if I could only integrate my WaterGuru…

So, going back to the API stuff @sh00t2kill, I discovered that the appKeys are all the same.

I decompiled the SDK and have been rummaging through to find api endpoints and such and found this beautiful section:

  public static final class e extends a {
    public e() {
      super("A614AF46-72E3-4E3B-8DBE-06A94D2401F7", "Pentair", null);
    }
  }
  
  @Metadata(mv = {1, 5, 1}, k = 1, xi = 48, d1 = {"\000\f\n\002\030\002\n\002\030\002\n\002\b\002\030\0002\0020\001B\005\006\002\020\002\006\003"}, d2 = {"Lcom/maytronics/iot/sdk/data/internal/local/AppType$MaytronicsUsers;", "Lcom/maytronics/iot/sdk/data/internal/local/AppType;", "()V", "MaytronicsIoTSDK_debug"})
  public static final class d extends a {
    public d() {
      super("346BDE92-53D1-4829-8A2E-B496014B586C", "Maytronics", null);
    }
  }
  
  @Metadata(mv = {1, 5, 1}, k = 1, xi = 48, d1 = {"\000\f\n\002\030\002\n\002\030\002\n\002\b\002\030\0002\0020\001B\005\006\002\020\002\006\003"}, d2 = {"Lcom/maytronics/iot/sdk/data/internal/local/AppType$MaytronicsTech;", "Lcom/maytronics/iot/sdk/data/internal/local/AppType;", "()V", "MaytronicsIoTSDK_debug"})
  public static final class c extends a {
    public c() {
      super("39C022DD-010F-475A-A32E-CEE9C89EA2CC", "MaytronicsTech", null);

This tells me that this is ok for everyone to know:

headers = {

  'appkey': '346BDE92-53D1-4829-8A2E-B496014B586C',

  'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',

}

Now, my question to you is, now that I have the token and secret key and such, where am I posting it to, to get into the database like you did?

You are right, thats the same key I have! Quality security right there.

Re dynobd, yeah you are right, It appears I didnt put that URL in my original message.

The one i used was https://dynamodb.eu-west-1.amazonaws.com/. I have a feeling postman automatically generated that for me as part of the AWS signature setup.

I just ran through my steps again end to end, and thats the thing that was missing.

Awesome! Thank you so much for that! I’m going to keep playing with it and see what I can come up with.

1 Like

From what I could gather, it seems that we need to work out how to map the values stored in DynamoDB to the app.

It appears to be a list of industrial type registers, or something like that.
Even just on/off for state, and catch alerts.

One thing that REALLY annoys me is that it doesnt send alerts when, eg its stuck or the basket is full, unless you actively open and update the state in the app.

2 Likes

Dude, I am pulling my hair out.

I’m having no luck posting, nor am I having luck using the boto3 aws python module.

Here’s where it’s failing for me:

An error occurred (AccessDeniedException) when calling the Query operation: User: arn:aws:sts::383511486912:federated-user/D2691ZNC is not authorized to perform: dynamodb:Query on resource: arn:aws:dynamodb:us-west-2:383511486912:table/maytronics_iot_history because no session policy allows the dynamodb:Query action

Whenever I try to post to dynamodb.

What method are you using to create your aws headers?

Ok, getting a little bit closer with the whole posting to the url you gave me. Created my aws signature header and all that, create the post you said, with headers and the data mentioned, and I get a response 400

b’{"__type":“com.amazon.coral.service#SerializationException”}’

1 Like

@sh00t2kill

So, I give up man, I did 100% what you did using postman, but I get this response:

{
    "__type": "com.amazon.coral.service#AccessDeniedException",
    "Message": "User: arn:aws:sts::383511486912:federated-user/D2691ZNC is not authorized to perform: dynamodb:Query on resource: arn:aws:dynamodb:eu-west-1:383511486912:table/maytronics_iot_history because no session policy allows the dynamodb:Query action"
}

Are you able to share your postman?

Does that help?

Looks like you have an extra header…

Just so everyone is in the loop, i threw together some python that pulls out the query from DynamoDb.

however, i havent been able to work out what any of the values mean, nor what they correspond to.
It doesnt help that my robot constantly goes offline in the mobile app either.

Im starting to wonder if sniffing the bluetooth packes would be a better approach.

The MQTT thing might have some legs. I might have some time tomorrow to investigate that further.

Unfortunately, it appears that the DynamoDB thing is no good.
It seems to only be historical data, and doesnt update until a cleaning cycle has completed.

It COULD be useful to pull in error states, if the last clean throw an error due to the filter being full, but outside of that it doesnt seem to have anything overly useful.

However, from what i can see digging through the SDK, it appears that its using the same credentials for DynamoDB and AWSIoTManager, so hopefully the credentials my script is grabbing can be re-used

Guys, i created a discord channel where we can chat about this.
If people are keen, join in

For those who are following this and havent joined the discord, we have a working component.

5 Likes