kopia lustrzana https://codeberg.org/argrento/huami-token
Download firmware and font pack (experimental, unstable, dangerous), add ID and ACT columns. Fix #12
rodzic
750b4eea06
commit
0f9d6f6aab
|
@ -4,3 +4,5 @@ notebooks
|
|||
*.zip
|
||||
__pycache__
|
||||
*.dump
|
||||
*.fw
|
||||
*.bin
|
||||
|
|
35
README.md
35
README.md
|
@ -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
|
||||
|
||||
|
|
|
@ -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
11
urls.py
|
@ -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'
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue