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
|
*.zip
|
||||||
__pycache__
|
__pycache__
|
||||||
*.dump
|
*.dump
|
||||||
|
*.fw
|
||||||
|
*.bin
|
||||||
|
|
35
README.md
35
README.md
|
@ -42,6 +42,8 @@ optional arguments:
|
||||||
Account Password
|
Account Password
|
||||||
-b, --bt_keys Get bluetooth tokens of paired devices
|
-b, --bt_keys Get bluetooth tokens of paired devices
|
||||||
-g, --gps Download A-GPS files
|
-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
|
-a, --all Do everything: get bluetooth tokens, download A-GPS
|
||||||
files
|
files
|
||||||
-n, --no_logout Do not logout, keep active session and display app
|
-n, --no_logout Do not logout, keep active session and display app
|
||||||
|
@ -60,11 +62,11 @@ Token: ['UaFHW53RJVYwqXaa7ncPQ']
|
||||||
Logging in...
|
Logging in...
|
||||||
Logged in! User id: 1234567890
|
Logged in! User id: 1234567890
|
||||||
Getting linked wearables...
|
Getting linked wearables...
|
||||||
+----------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| ACT | MAC | auth_key |
|
| ID | ACT | MAC | auth_key |
|
||||||
|-----+-------------------+--------------------------------------|
|
|-----+-----+-------------------+--------------------------------------|
|
||||||
| 1 | AB:CD:EF:12:34:56 | 0xa3c10e34e5c14637eea6b9efc06106 |
|
| 0 | 1 | AB:CD:EF:12:34:56 | 0xa3c10e34e5c14637eea6b9efc06106 |
|
||||||
+----------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
|
||||||
Logged out.
|
Logged out.
|
||||||
```
|
```
|
||||||
|
@ -99,12 +101,12 @@ Token: ['ALSG_CLOUDSRV_9B8D87D0EB77C71B45FF73B2266D922B']
|
||||||
Logging in...
|
Logging in...
|
||||||
Logged in! User id: 3000654321
|
Logged in! User id: 3000654321
|
||||||
Getting linked wearables...
|
Getting linked wearables...
|
||||||
+----------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| ACT | MAC | auth_key |
|
| ID | ACT | MAC | auth_key |
|
||||||
|-----+-------------------+--------------------------------------|
|
|-----+-----+-------------------+--------------------------------------|
|
||||||
| 1 | 12:34:56:AB:CD:EF | 0x3c10e34e5c1463527579996fa83e6d |
|
| 0 | 1 | 12:34:56:AB:CD:EF | 0x3c10e34e5c1463527579996fa83e6d |
|
||||||
| 0 | BA:DC:FE:21:43:65 | 0x00 |
|
| 1 | 0 | BA:DC:FE:21:43:65 | 0x00 |
|
||||||
+----------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
|
||||||
Logged out.
|
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,
|
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.
|
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
|
## Dependencies
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import urllib
|
||||||
import argparse
|
import argparse
|
||||||
import getpass
|
import getpass
|
||||||
import requests
|
import requests
|
||||||
|
import hashlib
|
||||||
|
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
|
@ -171,21 +172,60 @@ class HuamiAmazfit:
|
||||||
key_str = device_info['auth_key']
|
key_str = device_info['auth_key']
|
||||||
auth_key = '0x' + (key_str if key_str != '' else '00')
|
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(
|
_wearables.append(
|
||||||
{
|
{
|
||||||
'active_status': active_status,
|
'active_status': str(_wearable.get('activeStatus', '-1')),
|
||||||
'mac_address': mac_address,
|
'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
|
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:
|
def get_gps_data(self) -> None:
|
||||||
"""Download GPS packs: almanac and AGPS"""
|
"""Download GPS packs: almanac and AGPS"""
|
||||||
agps_packs = ["AGPS_ALM", "AGPSZIP"]
|
agps_packs = ["AGPS_ALM", "AGPSZIP"]
|
||||||
|
@ -196,7 +236,7 @@ class HuamiAmazfit:
|
||||||
headers['apptoken'] = self.app_token
|
headers['apptoken'] = self.app_token
|
||||||
|
|
||||||
for idx, agps_pack_name in enumerate(agps_packs):
|
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 = requests.get(agps_link.format(pack_name=agps_pack_name), headers=headers)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
agps_result = response.json()[0]
|
agps_result = response.json()[0]
|
||||||
|
@ -252,11 +292,20 @@ if __name__ == "__main__":
|
||||||
required=False,
|
required=False,
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help="Download A-GPS files")
|
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",
|
parser.add_argument("-a",
|
||||||
"--all",
|
"--all",
|
||||||
required=False,
|
required=False,
|
||||||
action='store_true',
|
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",
|
parser.add_argument("-n",
|
||||||
"--no_logout",
|
"--no_logout",
|
||||||
|
@ -269,9 +318,13 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
console = Console()
|
console = Console()
|
||||||
table = Table(show_header=True, header_style="bold", box=box.ASCII)
|
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("ACT", width=3, justify='center')
|
||||||
table.add_column("MAC", style="dim", width=17, 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":
|
if args.password is None and args.method == "amazfit":
|
||||||
args.password = getpass.getpass()
|
args.password = getpass.getpass()
|
||||||
|
@ -282,12 +335,31 @@ if __name__ == "__main__":
|
||||||
device.get_access_token()
|
device.get_access_token()
|
||||||
device.login()
|
device.login()
|
||||||
|
|
||||||
|
wearables = []
|
||||||
if args.bt_keys or args.all:
|
if args.bt_keys or args.all:
|
||||||
wearables = device.get_wearables()
|
wearables = device.get_wearables()
|
||||||
for wearable in wearables:
|
for idx, wearable in enumerate(wearables):
|
||||||
table.add_row(wearable['active_status'], wearable['mac_address'], wearable['auth_key'])
|
table.add_row(str(idx), wearable['active_status'],
|
||||||
|
wearable['mac_address'], wearable['auth_key'])
|
||||||
console.print(table)
|
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:
|
if args.gps or args.all:
|
||||||
device.get_gps_data()
|
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',
|
'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',
|
'data_short': 'https://api-mifit-us2.huami.com/users/{user_id}/deviceTypes/4/data',
|
||||||
'logout': 'https://account-us2.huami.com/v1/client/logout',
|
'logout': 'https://account-us2.huami.com/v1/client/logout',
|
||||||
|
'fw_updates': 'https://api-mifit-us2.huami.com/devices/ALL/hasNewVersion'
|
||||||
}
|
}
|
||||||
|
|
||||||
PAYLOADS = {
|
PAYLOADS = {
|
||||||
|
@ -55,4 +56,14 @@ PAYLOADS = {
|
||||||
'logout': {
|
'logout': {
|
||||||
'login_token': None
|
'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