@pss Thanks! Using as a direct proxy worked for me (I didn’t even try that as assumed it would fail ). I used mitmproxy - worth checking out as well.
Unfortunately in this case it was not doing a good job with the WebSocket connections (which is what it’s using). So I did a sslkeylogfile
dump, recorded the traffic using tcpdump
and then looked at the data in Wireshark.
@fejta It looks like the commands are also sent as JSON, for example:
{"method":"shadow","args":{"desired":{"shades":{"S1S":{"movePercent":100}}},"timeStamp":1597906370.327}}
For further technical info, the WebSocket URL is /rpc
, and the SSL cert is some sort of self signed cert from AWS.
Unfortunately, to get the detailed info on each blind (the name/description is the main thing), it makes a call to https://live.automate-arc.com/userInfo, returning data such as (slight censoring of IDs):
{
"code": 200,
"response": {
"devices": [
{
"deviceCode": "D",
"deviceType": "rollers",
"hubId": "v2-RA-Pulse-1005576",
"id": "S1S",
"isOwned": true,
"isStopped": true,
"limitsSet": 1,
"movePercent": 76,
"name": "Nook",
"online": true,
"roomId": "1597195710943",
"rssi": -77,
"tiltAngle": 0,
"version": "24",
"voltage": "11.3"
},
{
"deviceCode": "D",
"deviceType": "rollers",
"hubId": "v2-RA-Pulse-1005576",
"id": "D55",
"isOwned": true,
"isStopped": true,
"limitsSet": 1,
"movePercent": 82,
"name": "A1",
"online": true,
"roomId": "1597195710943",
"rssi": -70,
"tiltAngle": 52,
"version": "24",
"voltage": "11.4"
},
{
"deviceCode": "D",
"deviceType": "rollers",
"hubId": "v2-RA-Pulse-1005576",
"id": "PF8",
"isOwned": true,
"isStopped": true,
"limitsSet": 1,
"movePercent": 100,
"name": "A2",
"online": true,
"roomId": "1597195710943",
"rssi": -76,
"tiltAngle": 0,
"version": "24",
"voltage": "12.4"
},
{
"deviceCode": "D",
"deviceType": "rollers",
"hubId": "v2-RA-Pulse-1005576",
"id": "0R5",
"isOwned": true,
"isStopped": true,
"limitsSet": 1,
"movePercent": 100,
"name": "B1",
"online": true,
"roomId": "1597195710943",
"rssi": -84,
"tiltAngle": 0,
"version": "24",
"voltage": "11.3"
},
{
"deviceCode": "D",
"deviceType": "rollers",
"hubId": "v2-RA-Pulse-1005576",
"id": "YQX",
"isOwned": true,
"isStopped": true,
"limitsSet": 1,
"movePercent": 100,
"name": "B2",
"online": true,
"roomId": "1597195710943",
"rssi": -72,
"tiltAngle": 0,
"version": "24",
"voltage": "11.3"
},
{
"deviceCode": "D",
"deviceType": "rollers",
"hubId": "v2-RA-Pulse-1005576",
"id": "35W",
"isOwned": true,
"isStopped": true,
"limitsSet": 1,
"movePercent": 100,
"name": "C1",
"online": true,
"roomId": "1597195710943",
"rssi": -77,
"tiltAngle": 0,
"version": "24",
"voltage": "11.4"
},
{
"deviceCode": "D",
"deviceType": "rollers",
"hubId": "v2-RA-Pulse-1005576",
"id": "Q46",
"isOwned": true,
"isStopped": true,
"limitsSet": 1,
"movePercent": 100,
"name": " C2",
"online": true,
"roomId": "1597195710943",
"rssi": -78,
"tiltAngle": 0,
"version": "24",
"voltage": "11.2"
},
{
"deviceCode": "D",
"deviceType": "rollers",
"hubId": "v2-RA-Pulse-1005576",
"id": "VEB",
"isOwned": true,
"isStopped": true,
"limitsSet": 1,
"movePercent": 100,
"name": "Bins",
"online": true,
"roomId": "1597195710943",
"rssi": -80,
"tiltAngle": 0,
"version": "24",
"voltage": "11.2"
}
],
"hubs": [
"v2-RA-Pulse-1005576"
],
"locations": [
{
"hubs": [
{
"hubID": "v2-RA-Pulse-1005576",
"mac": "c4:4f:33:36:b0:35",
"name": "default",
"onlineLatest": 1597906236.90139,
"version": "1.0.0"
}
],
"id": "v2-e3f7fcd0-db9d-11ea-9f91-xxxxxxxxx",
"name": "Place",
"timersPaused": false
}
],
"rooms": [
{
"customPercent": 50,
"hubId": "v2-RA-Pulse-1005576",
"id": "1597195710943",
"isOwned": true,
"name": "Kitchen ",
"pictureKey": "barRoom"
}
],
"scenes": [],
"sharedHubs": [],
"timers": []
}
}
This request is made using Bearer auth (probably part of the AWS stack they are using), so I think it would be impractical to use this (short of getting them to login to HA, but I think given we have a local way to do it, the API maybe better).
There is also a request to https://live.automate-arc.com/appInfo/automate
, which gives this - implying they have an adjustable threshold for the battery (I have not looked closely yet, but looks about right based on the above). This also implies different batteries (and probably versions) have different thresholds - maybe it just does a regression in that range? It’s a bit different to what I was expecting.
{
"code": 200,
"response": {
"appVersion": "2.0.13",
"powerLevels": {
"A": {
"DEFAULT": {
"intervals": [],
"states": [
"ac_full"
]
}
},
"C": {
"10": {
"intervals": [
13.3,
15.5,
16.4,
17.5
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full",
"ac_full"
]
},
"DEFAULT": {
"intervals": [
8.946,
9.407,
12.6
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full"
]
}
},
"D": {
"14": {
"intervals": [
9.8,
11.8,
12.6,
14
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full",
"dc_full"
]
},
"20": {
"intervals": [
6.9,
7.9,
8.4,
12
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full",
"dc_full"
]
},
"22": {
"intervals": [
9.7,
11.7,
12.6
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full"
]
},
"24": {
"intervals": [
9.3,
11.6,
12.6,
13
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full",
"dc_full"
]
},
"25": {
"intervals": [
6.9,
7.8,
8.2
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full"
]
},
"DEFAULT": {
"intervals": [
8.946,
9.407,
12.6
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full"
]
}
},
"DEFAULT": {
"intervals": [
8.946,
9.407,
12.6
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full"
]
},
"d": {
"14": {
"intervals": [
9.9,
11.7,
12.6
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full"
]
},
"DEFAULT": {
"intervals": [
8.946,
9.407,
12.6
],
"states": [
"battery_low",
"battery_medium",
"battery_full",
"battery_full"
]
}
}
},
"timeOfRelease": 1597171465
}
}
If I get a chance I’ll see if I can do a quick test script to get info on the blinds and open/close them etc (not the name, rather the state if open/closed, and sending commands). Maybe a final solution could use port 1487 for getting data (name etc), then use the WebSocket connection for everything else?