Download firmware and font pack (experimental, unstable, dangerous), add ID and ACT columns. Fix #12

remotes/piggz/master
Kirill Snezhko 2021-02-24 02:08:48 +03:00
rodzic 750b4eea06
commit 0f9d6f6aab
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: AEC979562B0EE20B
4 zmienionych plików z 121 dodań i 23 usunięć

2
.gitignore vendored
Wyświetl plik

@ -4,3 +4,5 @@ notebooks
*.zip
__pycache__
*.dump
*.fw
*.bin

Wyświetl plik

@ -42,6 +42,8 @@ optional arguments:
Account Password
-b, --bt_keys Get bluetooth tokens of paired devices
-g, --gps Download A-GPS files
-f, --firmware Request firmware updates. Works only with -b/--bt_keys
argument. Extremely dangerous
-a, --all Do everything: get bluetooth tokens, download A-GPS
files
-n, --no_logout Do not logout, keep active session and display app
@ -60,11 +62,11 @@ Token: ['UaFHW53RJVYwqXaa7ncPQ']
Logging in...
Logged in! User id: 1234567890
Getting linked wearables...
+----------------------------------------------------------------+
| ACT | MAC | auth_key |
|-----+-------------------+--------------------------------------|
| 1 | AB:CD:EF:12:34:56 | 0xa3c10e34e5c14637eea6b9efc06106 |
+----------------------------------------------------------------+
+----------------------------------------------------------------------+
| ID | ACT | MAC | auth_key |
|-----+-----+-------------------+--------------------------------------|
| 0 | 1 | AB:CD:EF:12:34:56 | 0xa3c10e34e5c14637eea6b9efc06106 |
+----------------------------------------------------------------------+
Logged out.
```
@ -99,12 +101,12 @@ Token: ['ALSG_CLOUDSRV_9B8D87D0EB77C71B45FF73B2266D922B']
Logging in...
Logged in! User id: 3000654321
Getting linked wearables...
+----------------------------------------------------------------+
| ACT | MAC | auth_key |
|-----+-------------------+--------------------------------------|
| 1 | 12:34:56:AB:CD:EF | 0x3c10e34e5c1463527579996fa83e6d |
| 0 | BA:DC:FE:21:43:65 | 0x00 |
+----------------------------------------------------------------+
+----------------------------------------------------------------------+
| ID | ACT | MAC | auth_key |
|-----+-----+-------------------+--------------------------------------|
| 0 | 1 | 12:34:56:AB:CD:EF | 0x3c10e34e5c1463527579996fa83e6d |
| 1 | 0 | BA:DC:FE:21:43:65 | 0x00 |
+----------------------------------------------------------------------+
Logged out.
```
@ -115,6 +117,17 @@ active or not.
In this example I have two devices: the first one is my Amazfit Bip S watch,
the second one is my Xiaomi Mi Smart Scale.
## Experimental: updates download
This is extremely dangerous: flashing the wrong version can brick your device!
I am not responsible for any of problems that might arise.
Can be enabled with `-f/--firmware` argument. Will work only with `-b/--bt_keys` argument.
You should input the ID of a device, or `-1` to check for all.
Script will try to find updates for the firmware and the font pack for the device from
the table above.
## Dependencies

Wyświetl plik

@ -12,6 +12,7 @@ import urllib
import argparse
import getpass
import requests
import hashlib
from rich.console import Console
from rich.table import Table
@ -171,21 +172,60 @@ class HuamiAmazfit:
key_str = device_info['auth_key']
auth_key = '0x' + (key_str if key_str != '' else '00')
if 'activeStatus' in _wearable:
active_status = str(_wearable['activeStatus'])
else:
active_status = '-1'
_wearables.append(
{
'active_status': active_status,
'active_status': str(_wearable.get('activeStatus', '-1')),
'mac_address': mac_address,
'auth_key': auth_key
'auth_key': auth_key,
'device_source': str(_wearable.get('deviceSource', 0)),
'firmware_version': _wearable.get('firmwareVersion', 'v-1'),
'hardware_version': device_info.get('hardwareVersion', 'v-1'),
'production_source': device_info.get('productVersion', '0')
}
)
return _wearables
def get_firmware(self, _wearable: dict) -> None:
"""Check and download updates for the furmware and fonts"""
fw_url = urls.URLS["fw_updates"]
params = urls.PAYLOADS["fw_updates"]
params['deviceSource'] = _wearable['device_source']
params['firmwareVersion'] = _wearable['firmware_version']
params['hardwareVersion'] = _wearable['hardware_version']
params['productionSource'] = _wearable['production_source']
headers = {
'appplatform': 'android_phone',
'appname': 'com.huami.midong',
'lang': 'en_US'
}
response = requests.get(fw_url, params=params, headers=headers)
response.raise_for_status()
fw_response = response.json()
msgs = []
links = []
hashes = []
if 'firmwareUrl' in fw_response:
msgs.append('firmware')
links.append(fw_response['firmwareUrl'])
hashes.append(fw_response['firmwareMd5'])
if 'fontUrl' in fw_response:
msgs.append('font')
links.append(fw_response['fontUrl'])
hashes.append(fw_response['fontMd5'])
if not links:
print("No updates found!")
else:
for msg, link, hash_sum in zip(msgs, links, hashes):
file_name = link.split('/')[-1]
print(f"Downloading {file_name}...")
with requests.get(link, stream=True) as r:
with open(file_name, 'wb') as f:
shutil.copyfileobj(r.raw, f)
def get_gps_data(self) -> None:
"""Download GPS packs: almanac and AGPS"""
agps_packs = ["AGPS_ALM", "AGPSZIP"]
@ -196,7 +236,7 @@ class HuamiAmazfit:
headers['apptoken'] = self.app_token
for idx, agps_pack_name in enumerate(agps_packs):
print("Downloading {}...".format(agps_pack_name))
print(f"Downloading {agps_pack_name}...")
response = requests.get(agps_link.format(pack_name=agps_pack_name), headers=headers)
response.raise_for_status()
agps_result = response.json()[0]
@ -252,11 +292,20 @@ if __name__ == "__main__":
required=False,
action='store_true',
help="Download A-GPS files")
parser.add_argument("-f",
"--firmware",
required=False,
action='store_true',
help='Request firmware updates. Works only with -b/--bt_keys argument. '
'Extremely dangerous!')
parser.add_argument("-a",
"--all",
required=False,
action='store_true',
help="Do everything: get bluetooth tokens, download A-GPS files")
help="Do everything: get bluetooth tokens, download A-GPS files. But "
"do NOT download firmware updates")
parser.add_argument("-n",
"--no_logout",
@ -269,9 +318,13 @@ if __name__ == "__main__":
console = Console()
table = Table(show_header=True, header_style="bold", box=box.ASCII)
table.add_column("ID", width=3, justify='center')
table.add_column("ACT", width=3, justify='center')
table.add_column("MAC", style="dim", width=17, justify='center')
table.add_column("auth_key", width=50, justify='center')
table.add_column("auth_key", width=45, justify='center')
if args.firmware and not args.bt_keys:
parser.error("Can not use -f/--firmware without -b/--bt_keys!")
if args.password is None and args.method == "amazfit":
args.password = getpass.getpass()
@ -282,12 +335,31 @@ if __name__ == "__main__":
device.get_access_token()
device.login()
wearables = []
if args.bt_keys or args.all:
wearables = device.get_wearables()
for wearable in wearables:
table.add_row(wearable['active_status'], wearable['mac_address'], wearable['auth_key'])
for idx, wearable in enumerate(wearables):
table.add_row(str(idx), wearable['active_status'],
wearable['mac_address'], wearable['auth_key'])
console.print(table)
if args.firmware:
print("Downloading the firmware is untested and can brick your device. "
"I am not responsible for any problems that might arise.")
answer = input("Do you want to proceed? [yes/no] ")
if answer.lower() in ['yes', 'y', 'ye']:
wearable_id = input("ID of the device to check for updates (-1 for all of them): ")
if wearable_id == "-1":
print("Be extremely careful with downloaded files!")
for idx, wearable in enumerate(wearables):
print(f"\nChecking for device {idx}...")
device.get_firmware(wearable)
elif int(wearable_id) in range(0, len(wearables)):
device.get_firmware(wearables[wearable_id])
else:
print("Wrong input!")
if args.gps or args.all:
device.get_gps_data()

11
urls.py
Wyświetl plik

@ -11,6 +11,7 @@ URLS = {
'agps': 'https://api-mifit-us2.huami.com/apps/com.huami.midong/fileTypes/{pack_name}/files',
'data_short': 'https://api-mifit-us2.huami.com/users/{user_id}/deviceTypes/4/data',
'logout': 'https://account-us2.huami.com/v1/client/logout',
'fw_updates': 'https://api-mifit-us2.huami.com/devices/ALL/hasNewVersion'
}
PAYLOADS = {
@ -55,4 +56,14 @@ PAYLOADS = {
'logout': {
'login_token': None
},
'fw_updates': {
'productionSource': None,
'deviceSource': None,
'fontVersion': '0',
'fontFlag': '0',
'appVersion': '5.9.2-play_100355',
'firmwareVersion': None,
'hardwareVersion': None,
'support8Bytes': 'true'
}
}